Комментарии 43
Наивная реализация же на Python будет на 2-3 порядка медленее. А библиотеки типа NumPy — это и есть кирпичики. Если из них получается собрать алгоритм, то он будет быстрым. А если нет, то, увы, придётся переписывать на другом языке.
И да, мне тоже интересно, насколько самописная свёртка отличается по скорости работы от её реализации в Python. Может быть, когда-нибудь я это проверю.
Потребление памяти должно быть одинаково: в C# память для изображений выделяется в unmanaged пуле и управляется явно.
Для замера производительности я бы лучше использовал проверенную либу BenchmarkDotNet , а не самописный велосипед.
Можно, но я хотел использовать одинаковую реализацию для C# и C++.
Вот результаты для BenchmarkDotNet:
BenchmarkDotNet=v0.12.1, OS=arch Intel Core i7-2600K CPU 3.40GHz (Sandy Bridge), 1 CPU, 4 logical and 4 physical cores .NET Core SDK=5.0.101 [Host] : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT DefaultJob : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT | Method | Mean | Error | StdDev | |--------------------- |-------------:|----------:|----------:| | Sum_GetSetMethods | 114.99 us | 0.028 us | 0.026 us | | Sum_RefMethod | 117.90 us | 0.530 us | 0.470 us | | Sum_ThisProperty | 116.15 us | 0.219 us | 0.183 us | | Sum_Optimized | 40.74 us | 0.028 us | 0.027 us | | Sum_Avx | 21.23 us | 0.038 us | 0.032 us | | Rotate180 | 90.51 us | 0.024 us | 0.019 us | | Rotate180_Optimized | 34.80 us | 0.002 us | 0.002 us | | Rotate180_Avx | 14.82 us | 0.003 us | 0.003 us | | MedianFilter3x3 | 4,187.24 us | 12.817 us | 11.989 us | | MedianFilter5x5 | 11,535.95 us | 47.904 us | 42.466 us | | MedianFilter7x7 | 23,677.71 us | 13.734 us | 12.175 us | | Convolve | 5,592.16 us | 36.351 us | 34.003 us | | Convolve_Optimized | 2,923.87 us | 2.341 us | 1.955 us | | Convolve_Avx | 708.22 us | 0.856 us | 0.758 us | | Convolve_AvxIsolated | 512.15 us | 1.144 us | 1.070 us |
Как видно, мой велосипед не так уж и плох.
Она вызывает void Convolution::PerformVector() в котором векторные инструкции в явном виде не применяются.
Из которой, в свою очередь, вызывается ProcessUncheckedVector. Будьте немного внимательнее.
Плюс сами методы в тесте вызываются по указателю (через std::function) — это очень плохо способствует (по сути наверно убивает) инлайнинг и как следствия возможные дальнейшие оптимизации.
Вы написали ерунду. Нет никакого смысла оптимизировать сам вызов тестируемого метода. Вызов по указателю делается ровно один раз для каждой итерации. Это повышает время работы программы примерно на 0.001%. Внутри же тестируемого метода же никаких индирекций нет.
Еще неплохобы явно говорить компилятору что указатели которые используются в методах ссылаются на непересекающиеся куски памяти (__restrict).
И давно эта штука присутствует в стандарте C++?
Вообщем то что в нативной C++ реализации производительность больше на 10% мне как-то слабовато верится.
А зря. Об этом и статья. Примерно пару лет назад я делал подобное тестирование, и отставание C# от C++ было примерно в 2 раза для векторизованного метода. Сейчас же C# меня приятно удивил.
Лучше было попробовать нагуглить готовые заоптимизированные во все возможные щели реализации и сравнивать с ними а не писать самому.
Критикуете — предлагайте. Загуглите готовые заоптимизированные во все возможные щели реализации и предложите конкретные варианты. Если форкните проект и реализуете предложения самостоятельно, сообщество скажет дополнительное спасибо.
Вообще, как я написал выше, моя работа связана с обработкой изображений, и как раз я и отношусь к тем людям, которые пишут заоптимизированные во все возможные щели реализации, так что я могу вполне утверждать, что реализацию быстрее вы попросту не найдёте, а времени на то, чтобы подключить и разобраться с готовыми решениями уйдёт уйма.
Это как минимум неверно, потому что можно распараллелить все эти алгоритмы.
Конечно, можно. У меня есть и параллельные реализации алгоритмов. Но пропорции все равно сохраняются, поэтому приведение параллельных реализаций в данном случае нерелевантно: код станет сложнее, а выводы о сравнении производительности C# и C++ останутся теми же.
Правда, опять же, для распараллеливания используется велосипед: так получается, что собственная реализация для частных случаев оказывается эффективнее универсальных решений из эффективных библиотек (типа Intel TBB) за счёт меньшего оверхеда.
И по сути в большинстве случаев будет иметь значение именно латенси а не срупут.
Как раз для нейросетей, которые отлично параллелятся на множество медленных вычислителей, важнее throughput.
И не факт что синхронизация на C# и C++ будут прямо одинаково быстро работать.
Будут. Я проверял. Могу и по этой теме статью сделать, заодно и поясню, как так получилось, что моя реализация оказывается эффективнее библиотечной.
Во первых что значит «использует UB»
Имеется в виду, что отсутствуют проверки на выход из границу массива. Если бы поведение программы в этом случае было определённым, значит, имело бы место проверка, а значит, была бы ниже производительность.
Это какой то тролинг? Те примеры которые тут даны это как раз древнии вещи насколько это возможно, а вот разработку какая-нибудь невиданнаой досели архитектуры нейросети вполне можно назвать «чем-то новым».
Тогда предложите свой вариант алгоритма, который бы имело смысл протестировать. Я выбрал алгоритмы, которые, с одной стороны, достаточно быстро реализуются, а с другой стороны, делают что-то востребованное и сейчас.
Я говорю о том что инференс сети (конволющен сети в примерно 100% случаев для картинок) имеет условную скорость 100 картинок\сек то это ничего не значит если 1 изображение обрабатывается 0.3 сек например.
От задачи зависит. Например, для задачи повышения качества видеофайла важен именно первый параметр, а второй может быть хоть 30 секунд.
Например, замена вот этой строчки в функции
У меня закономерно меняется только время вычисления медианы.
Сам тест в MeasureExecutionTime вызывается N раз для одного и тоже изображения, что естественно уже при наверно 3-4 проходе заносит всю информацию в кеши. Это как-то не совсем правдоподобная ситуация.
Это как раз желаемое поведение — скорость доступа к памяти не зависит от языка, на котором написана программа, поэтому хотелось бы нивелировать влияние скорости доступа к памяти и замерить чистую производительность. Да, можно перед каждой итерацией пытаться очистить кэш, но предположу, что в этом случае к времени работы кода просто добавится константа в обоих случаях.
Чтобы провести более-менее «честный» эксперимент логично взять какой нить ролик, раскодровать его и использовать эти картинки как вход (без учета времени считывания в память естественно).
Так картинки сразу после раскодирования в кэше будут сидеть. Или предлагаете сначала декодировать сотню изображений, чтоб гарантированно в кэш не влезло, а затем уже обрабатывать их?
А еще для математики желательна бесплатная перегрузка операторов.
Сейчас подобные вещи стоит писать на CUDA/OpenCL.
Ваше утверждение тоже устарело. Зачем руками писать на CUDA/OpenCL, когда есть Tensorflow с обёрткой Tensorflow.NET или даже Matlab?
На самом деле, у каждого языка или фрейморка есть своё предназначение. И использование даже Tensorflow для некоторых задач — это уже оверкилл. Например, если я хочу продемонстрировать потенциальному заказчику работу нейросети, я не буду заставлять его устанавливать гигабайтные фреймворки. Я просто реализую нейросетку на голом C++ (CPU-only) без дополнительных зависимостей и передам ему компактный файлик, с которым он сможет играться.
с OpenCL немного не так все однозначно
так как его поддерживают и встореные в CPU видео карты, время копирования пркатически ноль… и возможно да будет выйгрышь
Нет, не упирается: при распараллеливании время выполнения уменьшается пропорционально числу потоков. Если бы упиралось в память, такого бы не наблюдалось.
Дополнительные потоки позволяют задействовать второй канал памяти. Кроме того, если размеры изображения не велики — все данные могут вмещаться в кеш процессора. Но даже для кеша L1 — 400 GB данных в секунду — это многовато. А ведь результаты нужно еще сохранять.
Операция свертки, или медианная фильтрация теоретически могут задействовать все вычислительные ресурсы процессора. Но там паритета вроде нет?
Согласен, упирается. Результаты сильно зависят от размера изображений:
64x64, 128x128 — 3.8 GFLOPS (L2 cache) — ~30GB/sec
256x256, 512x512 — ~3.2 GLOPS (L3 cache) — ~25GB/sec
1024x1024 и выше — 1.2 GFLOPS (memory) — ~10GB/sec
Не упирается только для свёртки. Распалеллеливание на 4 потока даёт закономерное ускорение почти в 4 раза вне зависимости от размера изображения.
Ваш процессор с AVX имеет производительность порядка 50 GFLOPS на ядро,
Если быть более точным, то 8 умножений и 8 сложений на цикл. В реальности это недостижимо — FMA-то нет. Linpack показывает пиковую производительность 25-30 GLOPS на ядро в зависимости от частоты процессора.
а для такого быстродействия потребуется загрузить 50 2 4 = 400 GB данных в секунду
Так это в теории, а на практике помимо VADDPS у нас будет аж 3 команды VMOVAPS, причём с необходимостью вычисления адреса, ещё регистр под счётчик надо держать. Для Sandy Bridge цифры такие:
VMOVAPS (r/mem) — latency 4, throughput 1 — их надо 3 штуки
VADDPS — latency 3, throughput 1
Итого имеем в лучшем случае: 2 цикла на прочитать данные, 3 цикла на сложить (ибо зависимость по данным), 4 цикла на записать, ну и 1 цикл на инкремент счётчика (но, скорее всего, он выполнится параллельно с операцией записи). То есть не больше 400 M подобных блоков в секунду, или 3.2 GFLOPS, что в целом соответствует цифрам из статьи (20 мкс, 65536 сложений = ~3.2 млрд).
Теоретически, можно ещё немного выжать производительности, избавившись от зависимости операций по данным и добившись задержки в 1 цикл для сложения и, если это вообще возможно, 1 цикл для записи. Но эффект будет наблюдаться только для L1 кэша.
Дополнительные потоки позволяют задействовать второй канал памяти.
Так в каждом ядре процессора по 2 блока для чтения. Разве процессор не способен задействовать оба канала из одного ядра?
Операция свертки, или медианная фильтрация теоретически могут задействовать все вычислительные ресурсы процессора. Но там паритета вроде нет?
Есть паритет между C# и g++ для свёртки. А вот clang уделывает за счёт оптимизаций. Если g++, судя по дизассемблеру, работал максимально аккуратно: не инлайнил Convolution::ProcessUncheckedVector, не разворачивал цикл, то clang заинлайнил практически всё.
Она заведомо (тк нет эквивалента в c#) не используется в бенчмарке?
Она заведомо (тк нет эквивалента в c#) не используется в бенчмарке?
Всё проще: она не используется, потому что я про неё раньше не знал. Да и не было цели сравнивать стандартные библиотеки.
Для медианы небольших размеров (3х3, 5х5) эффективнее использовать сортировочные сети, которые отлично векторизуются. А медину больших размеров на практике как-то и не приходилось использовать.
Мне приходилось для поиска дефектов (ядро до 31х31), но в этом случае я пользовался алгоритмом Хуанга, это "бегущая" медиана, которая вычисляется на основе локальной гистограммы, грубо говоря мы при смещении на пиксель добавляем новый столбец в гистограмму, а другой удаляем и корректируем значение медианы так чтобы на гистограмме слева и справа было одинаковое количество отсчётов (в чём суть медианы и есть).
Наверное вам будет интересно взглянуть на этот проект https://github.com/evilguest/linq2d
Там же есть ссылка на презентацию. Тут идея кодогенерации с использованием интрисинков и LINQ и дерева выражений.
Спасибо, любопытно.
Вообще, в одном из старых проектов у меня было сделано что-то похожее, но без использования LINQ: можно было написать что-то типа ((a + b) * c + c.Shift(1, 0)).Abs().Create();
, где внутри метода Create
аналогичным образом строилось Expression tree, которое потом компилировалось в метод из динамической сборки.
Привет. Мы задумали проект для сборки всея бенчмарков, неинтересно будет свой расшарить с нами, а точнее, со всеми? Здесь: https://github.com/asc-community/dotnet-benchmarks
0000000000003250 <_Z8ImageSumRK5ImageIfES2_RS0_>:
3250: 55 push rbp
3251: 48 89 e5 mov rbp,rsp
3254: 41 57 push r15
3256: 41 56 push r14
3258: 41 55 push r13
325a: 41 54 push r12
325c: 53 push rbx
325d: 48 83 e4 e0 and rsp,0xffffffffffffffe0
3261: 8b 42 0c mov eax,DWORD PTR [rdx+0xc]
3264: 89 44 24 fc mov DWORD PTR [rsp-0x4],eax
3268: 85 c0 test eax,eax
326a: 0f 8e a0 01 00 00 jle 3410 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1c0>
3270: 44 8b 5a 08 mov r11d,DWORD PTR [rdx+0x8]
3274: 45 85 db test r11d,r11d
3277: 0f 8e 93 01 00 00 jle 3410 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1c0>
327d: 8b 47 10 mov eax,DWORD PTR [rdi+0x10]
3280: 45 89 d9 mov r9d,r11d
3283: 45 89 dd mov r13d,r11d
3286: 45 89 de mov r14d,r11d
3289: 48 8b 1e mov rbx,QWORD PTR [rsi]
328c: 45 8d 7b ff lea r15d,[r11-0x1]
3290: 41 c1 e9 03 shr r9d,0x3
3294: 41 83 e5 f8 and r13d,0xfffffff8
3298: 4c 8b 27 mov r12,QWORD PTR [rdi]
329b: 49 c1 e1 05 shl r9,0x5
329f: 31 ff xor edi,edi
32a1: 89 44 24 e8 mov DWORD PTR [rsp-0x18],eax
32a5: 8b 46 10 mov eax,DWORD PTR [rsi+0x10]
32a8: 89 44 24 ec mov DWORD PTR [rsp-0x14],eax
32ac: 48 8b 02 mov rax,QWORD PTR [rdx]
32af: 48 89 44 24 f0 mov QWORD PTR [rsp-0x10],rax
32b4: 8b 42 10 mov eax,DWORD PTR [rdx+0x10]
32b7: 89 44 24 f8 mov DWORD PTR [rsp-0x8],eax
32bb: 44 89 d8 mov eax,r11d
32be: 83 e0 07 and eax,0x7
32c1: 89 44 24 e4 mov DWORD PTR [rsp-0x1c],eax
32c5: 83 e8 01 sub eax,0x1
32c8: 89 44 24 e0 mov DWORD PTR [rsp-0x20],eax
32cc: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
32d0: 8b 44 24 f8 mov eax,DWORD PTR [rsp-0x8]
32d4: 8b 4c 24 e8 mov ecx,DWORD PTR [rsp-0x18]
32d8: 8b 54 24 ec mov edx,DWORD PTR [rsp-0x14]
32dc: 0f af c7 imul eax,edi
32df: 0f af cf imul ecx,edi
32e2: 0f af d7 imul edx,edi
32e5: 48 98 cdqe
32e7: 48 03 44 24 f0 add rax,QWORD PTR [rsp-0x10]
32ec: 48 63 c9 movsxd rcx,ecx
32ef: 4d 8d 44 0c 04 lea r8,[r12+rcx*1+0x4]
32f4: 48 63 d2 movsxd rdx,edx
32f7: 4c 8d 54 13 04 lea r10,[rbx+rdx*1+0x4]
32fc: 48 89 c6 mov rsi,rax
32ff: 4c 29 c6 sub rsi,r8
3302: 49 89 c0 mov r8,rax
3305: 48 83 fe 18 cmp rsi,0x18
3309: 40 0f 97 c6 seta sil
330d: 4d 29 d0 sub r8,r10
3310: 49 83 f8 18 cmp r8,0x18
3314: 41 0f 97 c0 seta r8b
3318: 44 84 c6 test sil,r8b
331b: 0f 84 ff 00 00 00 je 3420 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1d0>
3321: 41 83 ff 02 cmp r15d,0x2
3325: 0f 86 f5 00 00 00 jbe 3420 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1d0>
332b: 41 83 ff 06 cmp r15d,0x6
332f: 0f 86 15 01 00 00 jbe 344a <_Z8ImageSumRK5ImageIfES2_RS0_+0x1fa>
3335: 4c 01 e1 add rcx,r12
3338: 48 01 da add rdx,rbx
333b: 31 f6 xor esi,esi
333d: 0f 1f 00 nop DWORD PTR [rax]
3340: c5 f8 10 14 31 vmovups xmm2,XMMWORD PTR [rcx+rsi*1]
3345: c4 e3 6d 18 44 31 10 01 vinsertf128 ymm0,ymm2,XMMWORD PTR [rcx+rsi*1+0x10],0x1
334d: c5 f8 10 1c 32 vmovups xmm3,XMMWORD PTR [rdx+rsi*1]
3352: c4 e3 65 18 4c 32 10 01 vinsertf128 ymm1,ymm3,XMMWORD PTR [rdx+rsi*1+0x10],0x1
335a: c5 fc 58 c1 vaddps ymm0,ymm0,ymm1
335e: c5 f8 11 04 30 vmovups XMMWORD PTR [rax+rsi*1],xmm0
3363: c4 e3 7d 19 44 30 10 01 vextractf128 XMMWORD PTR [rax+rsi*1+0x10],ymm0,0x1
336b: 48 83 c6 20 add rsi,0x20
336f: 4c 39 ce cmp rsi,r9
3372: 75 cc jne 3340 <_Z8ImageSumRK5ImageIfES2_RS0_+0xf0>
3374: 45 39 eb cmp r11d,r13d
3377: 0f 84 83 00 00 00 je 3400 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1b0>
337d: 83 7c 24 e0 02 cmp DWORD PTR [rsp-0x20],0x2
3382: 44 8b 54 24 e4 mov r10d,DWORD PTR [rsp-0x1c]
3387: 0f 86 d0 00 00 00 jbe 345d <_Z8ImageSumRK5ImageIfES2_RS0_+0x20d>
338d: 44 89 ee mov esi,r13d
3390: 45 89 e8 mov r8d,r13d
3393: 48 c1 e6 02 shl rsi,0x2
3397: c5 f8 10 24 31 vmovups xmm4,XMMWORD PTR [rcx+rsi*1]
339c: c5 d8 58 04 32 vaddps xmm0,xmm4,XMMWORD PTR [rdx+rsi*1]
33a1: c5 f8 11 04 30 vmovups XMMWORD PTR [rax+rsi*1],xmm0
33a6: 44 89 d6 mov esi,r10d
33a9: 83 e6 fc and esi,0xfffffffc
33ac: 41 01 f0 add r8d,esi
33af: 41 39 f2 cmp r10d,esi
33b2: 74 4c je 3400 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1b0>
33b4: 45 8d 50 01 lea r10d,[r8+0x1]
33b8: 49 63 f0 movsxd rsi,r8d
33bb: 48 c1 e6 02 shl rsi,0x2
33bf: c5 fa 10 04 32 vmovss xmm0,DWORD PTR [rdx+rsi*1]
33c4: c5 fa 58 04 31 vaddss xmm0,xmm0,DWORD PTR [rcx+rsi*1]
33c9: c5 fa 11 04 30 vmovss DWORD PTR [rax+rsi*1],xmm0
33ce: 45 39 d3 cmp r11d,r10d
33d1: 7e 2d jle 3400 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1b0>
33d3: c5 fa 10 44 31 04 vmovss xmm0,DWORD PTR [rcx+rsi*1+0x4]
33d9: 41 83 c0 02 add r8d,0x2
33dd: c5 fa 58 44 32 04 vaddss xmm0,xmm0,DWORD PTR [rdx+rsi*1+0x4]
33e3: c5 fa 11 44 30 04 vmovss DWORD PTR [rax+rsi*1+0x4],xmm0
33e9: 45 39 c3 cmp r11d,r8d
33ec: 7e 12 jle 3400 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1b0>
33ee: c5 fa 10 44 31 08 vmovss xmm0,DWORD PTR [rcx+rsi*1+0x8]
33f4: c5 fa 58 44 32 08 vaddss xmm0,xmm0,DWORD PTR [rdx+rsi*1+0x8]
33fa: c5 fa 11 44 30 08 vmovss DWORD PTR [rax+rsi*1+0x8],xmm0
3400: 83 c7 01 add edi,0x1
3403: 3b 7c 24 fc cmp edi,DWORD PTR [rsp-0x4]
3407: 0f 85 c3 fe ff ff jne 32d0 <_Z8ImageSumRK5ImageIfES2_RS0_+0x80>
340d: c5 f8 77 vzeroupper
3410: 48 8d 65 d8 lea rsp,[rbp-0x28]
3414: 5b pop rbx
3415: 41 5c pop r12
3417: 41 5d pop r13
3419: 41 5e pop r14
341b: 41 5f pop r15
341d: 5d pop rbp
341e: c3 ret
341f: 90 nop
3420: 31 f6 xor esi,esi
3422: 4c 01 e1 add rcx,r12
3425: 48 01 da add rdx,rbx
3428: 0f 1f 84 00 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0]
3430: c5 fa 10 04 b2 vmovss xmm0,DWORD PTR [rdx+rsi*4]
3435: c5 fa 58 04 b1 vaddss xmm0,xmm0,DWORD PTR [rcx+rsi*4]
343a: c5 fa 11 04 b0 vmovss DWORD PTR [rax+rsi*4],xmm0
343f: 48 83 c6 01 add rsi,0x1
3443: 4c 39 f6 cmp rsi,r14
3446: 75 e8 jne 3430 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1e0>
3448: eb b6 jmp 3400 <_Z8ImageSumRK5ImageIfES2_RS0_+0x1b0>
344a: 45 89 da mov r10d,r11d
344d: 31 f6 xor esi,esi
344f: 45 31 c0 xor r8d,r8d
3452: 4c 01 e1 add rcx,r12
3455: 48 01 da add rdx,rbx
3458: e9 36 ff ff ff jmp 3393 <_Z8ImageSumRK5ImageIfES2_RS0_+0x143>
345d: 45 89 e8 mov r8d,r13d
3460: e9 4f ff ff ff jmp 33b4 <_Z8ImageSumRK5ImageIfES2_RS0_+0x164>
3465: 66 66 2e 0f 1f 84 00 00 00 00 00 data16 nop WORD PTR cs:[rax+rax*1+0x0]
0000000000003470 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_>:
3470: 55 push rbp
3471: 48 89 e5 mov rbp,rsp
3474: 41 57 push r15
3476: 41 56 push r14
3478: 41 55 push r13
347a: 41 54 push r12
347c: 53 push rbx
347d: 48 83 e4 e0 and rsp,0xffffffffffffffe0
3481: 8b 42 0c mov eax,DWORD PTR [rdx+0xc]
3484: 89 44 24 ec mov DWORD PTR [rsp-0x14],eax
3488: 85 c0 test eax,eax
348a: 0f 8e 0a 02 00 00 jle 369a <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x22a>
3490: 4c 8b 3f mov r15,QWORD PTR [rdi]
3493: 8b 5a 08 mov ebx,DWORD PTR [rdx+0x8]
3496: 4c 8b 1e mov r11,QWORD PTR [rsi]
3499: 48 63 4e 10 movsxd rcx,DWORD PTR [rsi+0x10]
349d: 48 63 47 10 movsxd rax,DWORD PTR [rdi+0x10]
34a1: 4c 89 7c 24 f8 mov QWORD PTR [rsp-0x8],r15
34a6: 4c 8b 12 mov r10,QWORD PTR [rdx]
34a9: 89 5c 24 f0 mov DWORD PTR [rsp-0x10],ebx
34ad: 8b 72 10 mov esi,DWORD PTR [rdx+0x10]
34b0: 85 db test ebx,ebx
34b2: 0f 8e e2 01 00 00 jle 369a <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x22a>
34b8: 48 89 44 24 d8 mov QWORD PTR [rsp-0x28],rax
34bd: 8d 43 ff lea eax,[rbx-0x1]
34c0: 41 89 d8 mov r8d,ebx
34c3: 89 df mov edi,ebx
34c5: 89 44 24 e8 mov DWORD PTR [rsp-0x18],eax
34c9: 89 d8 mov eax,ebx
34cb: 83 e3 07 and ebx,0x7
34ce: 48 63 d6 movsxd rdx,esi
34d1: 83 e0 f8 and eax,0xfffffff8
34d4: 41 c1 e8 03 shr r8d,0x3
34d8: 89 5c 24 c8 mov DWORD PTR [rsp-0x38],ebx
34dc: 83 eb 01 sub ebx,0x1
34df: 48 89 54 24 e0 mov QWORD PTR [rsp-0x20],rdx
34e4: 49 c1 e0 05 shl r8,0x5
34e8: 4c 89 da mov rdx,r11
34eb: 48 89 4c 24 d0 mov QWORD PTR [rsp-0x30],rcx
34f0: 4c 89 f9 mov rcx,r15
34f3: 89 44 24 cc mov DWORD PTR [rsp-0x34],eax
34f7: 4c 89 d0 mov rax,r10
34fa: c7 44 24 f4 00 00 00 00 mov DWORD PTR [rsp-0xc],0x0
3502: 48 89 7c 24 b8 mov QWORD PTR [rsp-0x48],rdi
3507: 89 5c 24 c4 mov DWORD PTR [rsp-0x3c],ebx
350b: 0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0]
3510: 48 8d 79 04 lea rdi,[rcx+0x4]
3514: 48 89 c6 mov rsi,rax
3517: 49 89 d4 mov r12,rdx
351a: 48 29 fe sub rsi,rdi
351d: 48 89 c3 mov rbx,rax
3520: 49 89 c9 mov r9,rcx
3523: 4c 2b 4c 24 f8 sub r9,QWORD PTR [rsp-0x8]
3528: 4d 29 dc sub r12,r11
352b: 4c 29 d3 sub rbx,r10
352e: 4c 8d 6a 04 lea r13,[rdx+0x4]
3532: 48 83 fe 18 cmp rsi,0x18
3536: 48 89 c7 mov rdi,rax
3539: 40 0f 97 c6 seta sil
353d: 4c 29 ef sub rdi,r13
3540: 48 83 ff 18 cmp rdi,0x18
3544: 40 0f 97 c7 seta dil
3548: 40 84 fe test sil,dil
354b: 0f 84 5f 01 00 00 je 36b0 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x240>
3551: 8b 7c 24 e8 mov edi,DWORD PTR [rsp-0x18]
3555: 83 ff 02 cmp edi,0x2
3558: 0f 86 52 01 00 00 jbe 36b0 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x240>
355e: 83 ff 06 cmp edi,0x6
3561: 0f 86 73 01 00 00 jbe 36da <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x26a>
3567: 31 f6 xor esi,esi
3569: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
3570: c5 f8 10 14 31 vmovups xmm2,XMMWORD PTR [rcx+rsi*1]
3575: c4 e3 6d 18 44 31 10 01 vinsertf128 ymm0,ymm2,XMMWORD PTR [rcx+rsi*1+0x10],0x1
357d: c5 f8 10 1c 32 vmovups xmm3,XMMWORD PTR [rdx+rsi*1]
3582: c4 e3 65 18 4c 32 10 01 vinsertf128 ymm1,ymm3,XMMWORD PTR [rdx+rsi*1+0x10],0x1
358a: c5 fc 58 c1 vaddps ymm0,ymm0,ymm1
358e: c5 f8 11 04 30 vmovups XMMWORD PTR [rax+rsi*1],xmm0
3593: c4 e3 7d 19 44 30 10 01 vextractf128 XMMWORD PTR [rax+rsi*1+0x10],ymm0,0x1
359b: 48 83 c6 20 add rsi,0x20
359f: 4c 39 c6 cmp rsi,r8
35a2: 75 cc jne 3570 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x100>
35a4: 8b 7c 24 cc mov edi,DWORD PTR [rsp-0x34]
35a8: 39 7c 24 f0 cmp DWORD PTR [rsp-0x10],edi
35ac: 0f 84 c3 00 00 00 je 3675 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x205>
35b2: 83 7c 24 c4 02 cmp DWORD PTR [rsp-0x3c],0x2
35b7: 89 fe mov esi,edi
35b9: 44 8b 6c 24 c8 mov r13d,DWORD PTR [rsp-0x38]
35be: 76 35 jbe 35f5 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x185>
35c0: 4c 8b 74 24 f8 mov r14,QWORD PTR [rsp-0x8]
35c5: 48 c1 e6 02 shl rsi,0x2
35c9: 4d 8d 3c 33 lea r15,[r11+rsi*1]
35cd: c4 81 78 10 04 27 vmovups xmm0,XMMWORD PTR [r15+r12*1]
35d3: 4d 01 ce add r14,r9
35d6: c4 c1 78 58 04 36 vaddps xmm0,xmm0,XMMWORD PTR [r14+rsi*1]
35dc: 4c 01 d6 add rsi,r10
35df: c5 f8 11 04 1e vmovups XMMWORD PTR [rsi+rbx*1],xmm0
35e4: 44 89 ee mov esi,r13d
35e7: 83 e6 fc and esi,0xfffffffc
35ea: 01 f7 add edi,esi
35ec: 41 39 f5 cmp r13d,esi
35ef: 0f 84 80 00 00 00 je 3675 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x205>
35f5: 4c 8b 7c 24 f8 mov r15,QWORD PTR [rsp-0x8]
35fa: 48 63 f7 movsxd rsi,edi
35fd: 48 c1 e6 02 shl rsi,0x2
3601: 4d 8d 34 33 lea r14,[r11+rsi*1]
3605: 4d 8d 2c 32 lea r13,[r10+rsi*1]
3609: 49 01 f7 add r15,rsi
360c: c4 81 7a 10 04 0f vmovss xmm0,DWORD PTR [r15+r9*1]
3612: c4 81 7a 58 04 26 vaddss xmm0,xmm0,DWORD PTR [r14+r12*1]
3618: c4 c1 7a 11 44 1d 00 vmovss DWORD PTR [r13+rbx*1+0x0],xmm0
361f: 44 8d 6f 01 lea r13d,[rdi+0x1]
3623: 44 39 6c 24 f0 cmp DWORD PTR [rsp-0x10],r13d
3628: 7e 4b jle 3675 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x205>
362a: 4c 03 4c 24 f8 add r9,QWORD PTR [rsp-0x8]
362f: 83 c7 02 add edi,0x2
3632: 4c 8d 6e 04 lea r13,[rsi+0x4]
3636: 4f 8d 3c 2b lea r15,[r11+r13*1]
363a: c4 a1 7a 10 44 0e 04 vmovss xmm0,DWORD PTR [rsi+r9*1+0x4]
3641: 4f 8d 34 2a lea r14,[r10+r13*1]
3645: c4 81 7a 58 04 27 vaddss xmm0,xmm0,DWORD PTR [r15+r12*1]
364b: c4 c1 7a 11 04 1e vmovss DWORD PTR [r14+rbx*1],xmm0
3651: 39 7c 24 f0 cmp DWORD PTR [rsp-0x10],edi
3655: 7e 1e jle 3675 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x205>
3657: 48 83 c6 08 add rsi,0x8
365b: 4d 8d 2c 33 lea r13,[r11+rsi*1]
365f: c4 c1 7a 10 04 31 vmovss xmm0,DWORD PTR [r9+rsi*1]
3665: c4 81 7a 58 44 25 00 vaddss xmm0,xmm0,DWORD PTR [r13+r12*1+0x0]
366c: 49 8d 3c 32 lea rdi,[r10+rsi*1]
3670: c5 fa 11 04 1f vmovss DWORD PTR [rdi+rbx*1],xmm0
3675: 83 44 24 f4 01 add DWORD PTR [rsp-0xc],0x1
367a: 48 03 44 24 e0 add rax,QWORD PTR [rsp-0x20]
367f: 8b 5c 24 f4 mov ebx,DWORD PTR [rsp-0xc]
3683: 48 03 54 24 d0 add rdx,QWORD PTR [rsp-0x30]
3688: 48 03 4c 24 d8 add rcx,QWORD PTR [rsp-0x28]
368d: 3b 5c 24 ec cmp ebx,DWORD PTR [rsp-0x14]
3691: 0f 85 79 fe ff ff jne 3510 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0xa0>
3697: c5 f8 77 vzeroupper
369a: 48 8d 65 d8 lea rsp,[rbp-0x28]
369e: 5b pop rbx
369f: 41 5c pop r12
36a1: 41 5d pop r13
36a3: 41 5e pop r14
36a5: 41 5f pop r15
36a7: 5d pop rbp
36a8: c3 ret
36a9: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
36b0: 48 8b 7c 24 b8 mov rdi,QWORD PTR [rsp-0x48]
36b5: 31 f6 xor esi,esi
36b7: 66 0f 1f 84 00 00 00 00 00 nop WORD PTR [rax+rax*1+0x0]
36c0: c5 fa 10 04 b2 vmovss xmm0,DWORD PTR [rdx+rsi*4]
36c5: c5 fa 58 04 b1 vaddss xmm0,xmm0,DWORD PTR [rcx+rsi*4]
36ca: c5 fa 11 04 b0 vmovss DWORD PTR [rax+rsi*4],xmm0
36cf: 48 83 c6 01 add rsi,0x1
36d3: 48 39 fe cmp rsi,rdi
36d6: 75 e8 jne 36c0 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x250>
36d8: eb 9b jmp 3675 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x205>
36da: 44 8b 6c 24 f0 mov r13d,DWORD PTR [rsp-0x10]
36df: 31 f6 xor esi,esi
36e1: 31 ff xor edi,edi
36e3: e9 d8 fe ff ff jmp 35c0 <_Z17ImageSumOptimizedRK5ImageIfES2_RS0_+0x150>
36e8: 0f 1f 84 00 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0]
00000000000036f0 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_>:
36f0: 55 push rbp
36f1: 48 89 e5 mov rbp,rsp
36f4: 41 57 push r15
36f6: 41 56 push r14
36f8: 41 55 push r13
36fa: 41 54 push r12
36fc: 53 push rbx
36fd: 48 83 e4 e0 and rsp,0xffffffffffffffe0
3701: 48 89 74 24 e8 mov QWORD PTR [rsp-0x18],rsi
3706: 44 8b 62 08 mov r12d,DWORD PTR [rdx+0x8]
370a: 48 89 7c 24 f0 mov QWORD PTR [rsp-0x10],rdi
370f: 8b 72 0c mov esi,DWORD PTR [rdx+0xc]
3712: 41 8d 44 24 07 lea eax,[r12+0x7]
3717: 45 85 e4 test r12d,r12d
371a: 41 0f 49 c4 cmovns eax,r12d
371e: 89 74 24 f8 mov DWORD PTR [rsp-0x8],esi
3722: 83 e0 f8 and eax,0xfffffff8
3725: 89 44 24 fc mov DWORD PTR [rsp-0x4],eax
3729: 85 f6 test esi,esi
372b: 0f 8e ee 01 00 00 jle 391f <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x22f>
3731: 8d 70 ff lea esi,[rax-0x1]
3734: f7 d0 not eax
3736: 48 89 d3 mov rbx,rdx
3739: c1 ee 03 shr esi,0x3
373c: 45 31 c9 xor r9d,r9d
373f: 89 44 24 e4 mov DWORD PTR [rsp-0x1c],eax
3743: 83 c6 01 add esi,0x1
3746: 48 c1 e6 05 shl rsi,0x5
374a: 66 0f 1f 44 00 00 nop WORD PTR [rax+rax*1+0x0]
3750: 48 8b 44 24 f0 mov rax,QWORD PTR [rsp-0x10]
3755: 31 ff xor edi,edi
3757: 44 8b 44 24 fc mov r8d,DWORD PTR [rsp-0x4]
375c: 8b 50 10 mov edx,DWORD PTR [rax+0x10]
375f: 41 0f af d1 imul edx,r9d
3763: 48 63 d2 movsxd rdx,edx
3766: 48 03 10 add rdx,QWORD PTR [rax]
3769: 48 8b 44 24 e8 mov rax,QWORD PTR [rsp-0x18]
376e: 8b 48 10 mov ecx,DWORD PTR [rax+0x10]
3771: 41 0f af c9 imul ecx,r9d
3775: 48 63 c9 movsxd rcx,ecx
3778: 48 03 08 add rcx,QWORD PTR [rax]
377b: 8b 43 10 mov eax,DWORD PTR [rbx+0x10]
377e: 41 0f af c1 imul eax,r9d
3782: 48 98 cdqe
3784: 48 03 03 add rax,QWORD PTR [rbx]
3787: 45 85 c0 test r8d,r8d
378a: 7e 30 jle 37bc <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0xcc>
378c: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
3790: c5 fc 28 14 39 vmovaps ymm2,YMMWORD PTR [rcx+rdi*1]
3795: c5 ec 58 04 3a vaddps ymm0,ymm2,YMMWORD PTR [rdx+rdi*1]
379a: c5 fc 29 04 38 vmovaps YMMWORD PTR [rax+rdi*1],ymm0
379f: 48 83 c7 20 add rdi,0x20
37a3: 48 39 f7 cmp rdi,rsi
37a6: 75 e8 jne 3790 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0xa0>
37a8: 8b 7b 0c mov edi,DWORD PTR [rbx+0xc]
37ab: 48 01 f2 add rdx,rsi
37ae: 48 01 f1 add rcx,rsi
37b1: 48 01 f0 add rax,rsi
37b4: 44 8b 63 08 mov r12d,DWORD PTR [rbx+0x8]
37b8: 89 7c 24 f8 mov DWORD PTR [rsp-0x8],edi
37bc: 44 39 64 24 fc cmp DWORD PTR [rsp-0x4],r12d
37c1: 0f 8d 46 01 00 00 jge 390d <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x21d>
37c7: 44 89 e7 mov edi,r12d
37ca: 2b 7c 24 fc sub edi,DWORD PTR [rsp-0x4]
37ce: 49 89 c2 mov r10,rax
37d1: 4c 8d 5a 04 lea r11,[rdx+0x4]
37d5: 4d 29 da sub r10,r11
37d8: 44 8d 47 ff lea r8d,[rdi-0x1]
37dc: 49 83 fa 18 cmp r10,0x18
37e0: 41 0f 97 c3 seta r11b
37e4: 41 83 f8 02 cmp r8d,0x2
37e8: 41 0f 97 c2 seta r10b
37ec: 45 84 d3 test r11b,r10b
37ef: 0f 84 3b 01 00 00 je 3930 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x240>
37f5: 4c 8d 59 04 lea r11,[rcx+0x4]
37f9: 49 89 c2 mov r10,rax
37fc: 4d 29 da sub r10,r11
37ff: 49 83 fa 18 cmp r10,0x18
3803: 0f 86 27 01 00 00 jbe 3930 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x240>
3809: 41 83 f8 06 cmp r8d,0x6
380d: 0f 86 4f 01 00 00 jbe 3962 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x272>
3813: 41 89 fa mov r10d,edi
3816: 45 31 c0 xor r8d,r8d
3819: 41 c1 ea 03 shr r10d,0x3
381d: 49 c1 e2 05 shl r10,0x5
3821: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
3828: c4 a1 78 10 1c 02 vmovups xmm3,XMMWORD PTR [rdx+r8*1]
382e: c4 a3 65 18 44 02 10 01 vinsertf128 ymm0,ymm3,XMMWORD PTR [rdx+r8*1+0x10],0x1
3836: c4 a1 78 10 24 01 vmovups xmm4,XMMWORD PTR [rcx+r8*1]
383c: c4 a3 5d 18 4c 01 10 01 vinsertf128 ymm1,ymm4,XMMWORD PTR [rcx+r8*1+0x10],0x1
3844: c5 fc 58 c1 vaddps ymm0,ymm0,ymm1
3848: c4 a1 78 11 04 00 vmovups XMMWORD PTR [rax+r8*1],xmm0
384e: c4 a3 7d 19 44 00 10 01 vextractf128 XMMWORD PTR [rax+r8*1+0x10],ymm0,0x1
3856: 49 83 c0 20 add r8,0x20
385a: 4d 39 c2 cmp r10,r8
385d: 75 c9 jne 3828 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x138>
385f: 44 8b 5c 24 fc mov r11d,DWORD PTR [rsp-0x4]
3864: 41 89 ff mov r15d,edi
3867: 41 83 e7 f8 and r15d,0xfffffff8
386b: 45 89 fa mov r10d,r15d
386e: 4e 8d 04 95 00 00 00 00 lea r8,[r10*4+0x0]
3876: 4e 8d 34 02 lea r14,[rdx+r8*1]
387a: 45 01 fb add r11d,r15d
387d: 4e 8d 2c 01 lea r13,[rcx+r8*1]
3881: 49 01 c0 add r8,rax
3884: 44 39 ff cmp edi,r15d
3887: 0f 84 80 00 00 00 je 390d <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x21d>
388d: 44 29 ff sub edi,r15d
3890: 44 8d 7f ff lea r15d,[rdi-0x1]
3894: 41 83 ff 02 cmp r15d,0x2
3898: 76 2d jbe 38c7 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x1d7>
389a: c4 a1 78 10 04 91 vmovups xmm0,XMMWORD PTR [rcx+r10*4]
38a0: c4 a1 78 58 04 92 vaddps xmm0,xmm0,XMMWORD PTR [rdx+r10*4]
38a6: 89 fa mov edx,edi
38a8: 83 e2 fc and edx,0xfffffffc
38ab: 41 01 d3 add r11d,edx
38ae: c4 a1 78 11 04 90 vmovups XMMWORD PTR [rax+r10*4],xmm0
38b4: 89 d0 mov eax,edx
38b6: 48 c1 e0 02 shl rax,0x2
38ba: 49 01 c6 add r14,rax
38bd: 49 01 c5 add r13,rax
38c0: 49 01 c0 add r8,rax
38c3: 39 d7 cmp edi,edx
38c5: 74 46 je 390d <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x21d>
38c7: c4 c1 7a 10 06 vmovss xmm0,DWORD PTR [r14]
38cc: 41 8d 43 01 lea eax,[r11+0x1]
38d0: c4 c1 7a 58 45 00 vaddss xmm0,xmm0,DWORD PTR [r13+0x0]
38d6: c4 c1 7a 11 00 vmovss DWORD PTR [r8],xmm0
38db: 41 39 c4 cmp r12d,eax
38de: 7e 2d jle 390d <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x21d>
38e0: c4 c1 7a 10 46 04 vmovss xmm0,DWORD PTR [r14+0x4]
38e6: 41 83 c3 02 add r11d,0x2
38ea: c4 c1 7a 58 45 04 vaddss xmm0,xmm0,DWORD PTR [r13+0x4]
38f0: c4 c1 7a 11 40 04 vmovss DWORD PTR [r8+0x4],xmm0
38f6: 45 39 dc cmp r12d,r11d
38f9: 7e 12 jle 390d <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x21d>
38fb: c4 c1 7a 10 46 08 vmovss xmm0,DWORD PTR [r14+0x8]
3901: c4 c1 7a 58 45 08 vaddss xmm0,xmm0,DWORD PTR [r13+0x8]
3907: c4 c1 7a 11 40 08 vmovss DWORD PTR [r8+0x8],xmm0
390d: 41 83 c1 01 add r9d,0x1
3911: 44 3b 4c 24 f8 cmp r9d,DWORD PTR [rsp-0x8]
3916: 0f 8c 34 fe ff ff jl 3750 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x60>
391c: c5 f8 77 vzeroupper
391f: 48 8d 65 d8 lea rsp,[rbp-0x28]
3923: 5b pop rbx
3924: 41 5c pop r12
3926: 41 5d pop r13
3928: 41 5e pop r14
392a: 41 5f pop r15
392c: 5d pop rbp
392d: c3 ret
392e: 66 90 xchg ax,ax
3930: 8b 7c 24 e4 mov edi,DWORD PTR [rsp-0x1c]
3934: 44 01 e7 add edi,r12d
3937: 4c 8d 04 bd 04 00 00 00 lea r8,[rdi*4+0x4]
393f: 31 ff xor edi,edi
3941: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
3948: c5 fa 10 04 39 vmovss xmm0,DWORD PTR [rcx+rdi*1]
394d: c5 fa 58 04 3a vaddss xmm0,xmm0,DWORD PTR [rdx+rdi*1]
3952: c5 fa 11 04 38 vmovss DWORD PTR [rax+rdi*1],xmm0
3957: 48 83 c7 04 add rdi,0x4
395b: 49 39 f8 cmp r8,rdi
395e: 75 e8 jne 3948 <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x258>
3960: eb ab jmp 390d <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x21d>
3962: 44 8b 5c 24 fc mov r11d,DWORD PTR [rsp-0x4]
3967: 49 89 c0 mov r8,rax
396a: 49 89 cd mov r13,rcx
396d: 49 89 d6 mov r14,rdx
3970: 45 31 d2 xor r10d,r10d
3973: e9 22 ff ff ff jmp 389a <_Z16ImageSumUsingAvxRK5ImageIfES2_RS0_+0x1aa>
3978: 0f 1f 84 00 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0]
как раз ImageSumOptimized не самая показательная, вернее самая простая для компилятора
а что на счет Convolve 7x7 или медианы?
ну не может копилятор сам векторизировать их… :-)
Да, свёртку компилятор не векторизовал (собственно, цифры в таблице это и показывают):
0000000000004310 <_ZN11Convolution25ProcessUncheckedOptimizedEii>:
4310: 55 push rbp
4311: 41 57 push r15
4313: 41 56 push r14
4315: 41 55 push r13
4317: 41 54 push r12
4319: 53 push rbx
431a: 89 54 24 dc mov DWORD PTR [rsp-0x24],edx
431e: 44 8b 5f 24 mov r11d,DWORD PTR [rdi+0x24]
4322: c5 f8 57 c0 vxorps xmm0,xmm0,xmm0
4326: 48 63 c6 movsxd rax,esi
4329: 48 89 44 24 e8 mov QWORD PTR [rsp-0x18],rax
432e: 45 85 db test r11d,r11d
4331: 48 89 7c 24 e0 mov QWORD PTR [rsp-0x20],rdi
4336: 0f 88 50 01 00 00 js 448c <_ZN11Convolution25ProcessUncheckedOptimizedEii+0x17c>
433c: 44 8b 57 20 mov r10d,DWORD PTR [rdi+0x20]
4340: 45 85 d2 test r10d,r10d
4343: 0f 88 43 01 00 00 js 448c <_ZN11Convolution25ProcessUncheckedOptimizedEii+0x17c>
4349: 48 8b 7c 24 e0 mov rdi,QWORD PTR [rsp-0x20]
434e: 48 8b 07 mov rax,QWORD PTR [rdi]
4351: 48 8b 4f 08 mov rcx,QWORD PTR [rdi+0x8]
4355: 44 8b 48 10 mov r9d,DWORD PTR [rax+0x10]
4359: 4c 8b 29 mov r13,QWORD PTR [rcx]
435c: 48 63 57 18 movsxd rdx,DWORD PTR [rdi+0x18]
4360: 48 8b 00 mov rax,QWORD PTR [rax]
4363: 4c 63 71 10 movsxd r14,DWORD PTR [rcx+0x10]
4367: 45 31 ff xor r15d,r15d
436a: 45 85 db test r11d,r11d
436d: 45 0f 48 df cmovs r11d,r15d
4371: 41 83 c3 01 add r11d,0x1
4375: 49 8d 72 01 lea rsi,[r10+0x1]
4379: 89 f3 mov ebx,esi
437b: 83 e3 03 and ebx,0x3
437e: 83 e6 fc and esi,0xfffffffc
4381: 48 8b 4c 24 e8 mov rcx,QWORD PTR [rsp-0x18]
4386: 48 8d 0c 8d 00 00 00 00 lea rcx,[rcx*4+0x0]
438e: 48 c1 e2 02 shl rdx,0x2
4392: 48 29 d1 sub rcx,rdx
4395: 48 8d 14 08 lea rdx,[rax+rcx*1]
4399: 48 83 c2 0c add rdx,0xc
439d: 48 89 54 24 f0 mov QWORD PTR [rsp-0x10],rdx
43a2: 8b 6c 24 dc mov ebp,DWORD PTR [rsp-0x24]
43a6: 2b 6f 1c sub ebp,DWORD PTR [rdi+0x1c]
43a9: 41 0f af e9 imul ebp,r9d
43ad: 48 01 c1 add rcx,rax
43b0: 48 89 4c 24 f8 mov QWORD PTR [rsp-0x8],rcx
43b5: 49 8d 45 0c lea rax,[r13+0xc]
43b9: c5 f8 57 c0 vxorps xmm0,xmm0,xmm0
43bd: eb 17 jmp 43d6 <_ZN11Convolution25ProcessUncheckedOptimizedEii+0xc6>
43bf: 90 nop
43c0: 49 83 c7 01 add r15,0x1
43c4: 44 01 cd add ebp,r9d
43c7: 4c 01 f0 add rax,r14
43ca: 4d 01 f5 add r13,r14
43cd: 4d 39 df cmp r15,r11
43d0: 0f 84 b6 00 00 00 je 448c <_ZN11Convolution25ProcessUncheckedOptimizedEii+0x17c>
43d6: 4c 63 c5 movsxd r8,ebp
43d9: 41 83 fa 03 cmp r10d,0x3
43dd: 0f 83 0d 00 00 00 jae 43f0 <_ZN11Convolution25ProcessUncheckedOptimizedEii+0xe0>
43e3: 45 31 e4 xor r12d,r12d
43e6: e9 64 00 00 00 jmp 444f <_ZN11Convolution25ProcessUncheckedOptimizedEii+0x13f>
43eb: 0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0]
43f0: 48 8b 4c 24 f0 mov rcx,QWORD PTR [rsp-0x10]
43f5: 4a 8d 14 01 lea rdx,[rcx+r8*1]
43f9: 45 31 e4 xor r12d,r12d
43fc: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
4400: c4 a1 7a 10 4c a2 f4 vmovss xmm1,DWORD PTR [rdx+r12*4-0xc]
4407: c4 a1 7a 10 54 a2 f8 vmovss xmm2,DWORD PTR [rdx+r12*4-0x8]
440e: c4 a1 72 59 4c a0 f4 vmulss xmm1,xmm1,DWORD PTR [rax+r12*4-0xc]
4415: c4 a1 6a 59 54 a0 f8 vmulss xmm2,xmm2,DWORD PTR [rax+r12*4-0x8]
441c: c5 fa 58 c1 vaddss xmm0,xmm0,xmm1
4420: c4 a1 7a 10 4c a2 fc vmovss xmm1,DWORD PTR [rdx+r12*4-0x4]
4427: c4 a1 72 59 4c a0 fc vmulss xmm1,xmm1,DWORD PTR [rax+r12*4-0x4]
442e: c5 fa 58 c2 vaddss xmm0,xmm0,xmm2
4432: c4 a1 7a 10 14 a2 vmovss xmm2,DWORD PTR [rdx+r12*4]
4438: c4 a1 6a 59 14 a0 vmulss xmm2,xmm2,DWORD PTR [rax+r12*4]
443e: c5 fa 58 c1 vaddss xmm0,xmm0,xmm1
4442: c5 fa 58 c2 vaddss xmm0,xmm0,xmm2
4446: 49 83 c4 04 add r12,0x4
444a: 4c 39 e6 cmp rsi,r12
444d: 75 b1 jne 4400 <_ZN11Convolution25ProcessUncheckedOptimizedEii+0xf0>
444f: 48 85 db test rbx,rbx
4452: 0f 84 68 ff ff ff je 43c0 <_ZN11Convolution25ProcessUncheckedOptimizedEii+0xb0>
4458: 4a 8d 14 a5 00 00 00 00 lea rdx,[r12*4+0x0]
4460: 4c 01 ea add rdx,r13
4463: 4b 8d 3c a0 lea rdi,[r8+r12*4]
4467: 48 03 7c 24 f8 add rdi,QWORD PTR [rsp-0x8]
446c: 31 c9 xor ecx,ecx
446e: 66 90 xchg ax,ax
4470: c5 fa 10 0c 8f vmovss xmm1,DWORD PTR [rdi+rcx*4]
4475: c5 f2 59 0c 8a vmulss xmm1,xmm1,DWORD PTR [rdx+rcx*4]
447a: c5 fa 58 c1 vaddss xmm0,xmm0,xmm1
447e: 48 83 c1 01 add rcx,0x1
4482: 48 39 cb cmp rbx,rcx
4485: 75 e9 jne 4470 <_ZN11Convolution25ProcessUncheckedOptimizedEii+0x160>
4487: e9 34 ff ff ff jmp 43c0 <_ZN11Convolution25ProcessUncheckedOptimizedEii+0xb0>
448c: 48 8b 44 24 e0 mov rax,QWORD PTR [rsp-0x20]
4491: 48 8b 40 10 mov rax,QWORD PTR [rax+0x10]
4495: 48 63 48 10 movsxd rcx,DWORD PTR [rax+0x10]
4499: 48 63 54 24 dc movsxd rdx,DWORD PTR [rsp-0x24]
449e: 48 0f af d1 imul rdx,rcx
44a2: 48 03 10 add rdx,QWORD PTR [rax]
44a5: 48 8b 44 24 e8 mov rax,QWORD PTR [rsp-0x18]
44aa: c5 fa 11 04 82 vmovss DWORD PTR [rdx+rax*4],xmm0
44af: 5b pop rbx
44b0: 41 5c pop r12
44b2: 41 5d pop r13
44b4: 41 5e pop r14
44b6: 41 5f pop r15
44b8: 5d pop rbp
44b9: c3 ret
44ba: 66 0f 1f 44 00 00 nop WORD PTR [rax+rax*1+0x0]
А реализация медианы с классической сортировкой не векторизуема.
думаю все будет заметно быстрее
как это написать на на C# — не спрашивайте, не знаю :-)
а медиану сортировкой из стандартной библиотеке… были вы у меня в группе… руки бы оторвал :-)
если уж, стоит написать темплейтный класс и параметаризировать его по радиусу а не передавать его переменной в конструктор
тогда внутринии циклы станут константами 3,5,7
компилятору станет проще оптимизировать…
и не факт что C# проиграет так же сильно…
если вы избавитесь от класса Image с его оператором скобки и на прямую будете обрашаться к буферу
Вообще-то в optimized версии именно это и происходит — я работаю с указателями.
а медиану сортировкой из стандартной библиотеке… были вы у меня в группе… руки бы оторвал :-)
Преждевременные оптимизации — зло. Этот тот случай, когда больше времени уйдёт на написание кода.
если уж, стоит написать темплейтный класс и параметаризировать его по радиусу а не передавать его переменной в конструктор
Если сёрьзно думать об оптимизации, тогда берётся сортировочная сеть с фиксированным числом операций. И вот она просто замечательно векторизуется.
А можно упороться ещё дальше: мы ведь проходим скользящим окном. Нам не нужно при смещении на 1 пиксель всё пересортировывать заново. Нам нужен супер-алгоритм, который это умеет учитывать.
Зачем супер? Если сильно не замарачиваться, то проще скользащего окна + std::multiset сложно что-то придумать. Кода примерно столько же, как сейчас, плюс учет границ почти бесплатно. На больших окнах и 10К картинках для томографии (16 бит) реальные тесты давали что-то вроде 1.5 минуты против 2 часов наивной реализации.
Сравниваем производительность C# и C++ в задачах обработки изображений