О векторном умножении - финал
Исключительно в режиме записок для себя, вижу что интерес к теме у читателей потерялся, продолжаем тему скалярного произведения и матричного цветового преобразования.
Ассемблерные упражнения на тему векторных расширений.
SSE2-код
Сразу оговорка про Core2: быстродействие всех рассмотренных ниже сниппетов на этом процессоре практически одинаково, судя по всему все уперлось в память. А вот разница на Core i7-AVX довольно существенна.
Код, аналогичный тому, что делает хороший компилятор из векторного кода.
{
int i;
__m128 m0 = _mm_load_ps(matT[0]);
__m128 m1 = _mm_load_ps(matT[1]);
__m128 m2 = _mm_load_ps(matT[2]);
__m128 m3 = _mm_load_ps(matT[3]);
for(i=0;i<sz;i++)
{
//1 начало чтения данных
__m128 x0 = _mm_load_ps1(&q[i*4]);
__m128 x1 = _mm_load_ps1(&q[i*4+1]);
__m128 x2 = _mm_load_ps1(&q[i*4+2]);
__m128 x3 = _mm_load_ps1(&q[i*4+3]);
//2 все прочитано
__m128 r0 = _mm_mul_ps(x0,m0);
__m128 r1 = _mm_mul_ps(x1,m1);
__m128 r2 = _mm_mul_ps(x2,m2);
__m128 r3 = _mm_mul_ps(x3,m3);
__m128 t1 = _mm_add_ps(r0,r1);
__m128 t2 = _mm_add_ps(r2,r3);
__m128 t3 = _mm_add_ps(t1,t2);
_mm_store_ps(&q[i*4],t3);
}
};
}
Каждый load_ps1 превращается в movss + shuffle, что полностью аналогично тому коду, который сделал clang. На Core i7-AVX @4.5Ghz получается 570 Mpix/sec, что несколько быстрее, чем скалярное умножение командой процессора (SSE4.1), при том что код остается SSE2.
Можно сделать лучше (только кусок от //1 до //2 в предыдущем сниппете):
__m128 x0 = _mm_load_ps(&q[i*4]);
__m128 x1 = x0;
x1 = _mm_shuffle_ps(x1,x1,0x55);
__m128 x2 = x0;
x2 = _mm_shuffle_ps(x2,x2,0xAA);
__m128 x3 = x0;
x3 = _mm_shuffle_ps(x3,x3,0xff);
x0 = _mm_shuffle_ps(x0,x0,0);
//2
AVX-варианты
Раз сравниваем с 256-битным vdpps, попробуем и другие варианты.Вариант с 8-ю movss в цикле (аналог sse_load1) оказался медленнее SSE2-варианта: не хватает регистров и используются промежуточное сохранение на стеке.
256-битный вариант с _mm_broadcast_ss: то же быстродействие, что у 128-битного варианта (в пределах разброса результатов).
Вариант с одним 256-битным load:
{
int i;
__m256 m0 = _mm256_load_ps(matTX2[0]);
__m256 m1 = _mm256_load_ps(matTX2[1]);
__m256 m2 = _mm256_load_ps(matTX2[2]);
__m256 m3 = _mm256_load_ps(matTX2[3]);
for(i=0;i<sz;i+=2)
{
__m256 x0 = _mm256_load_ps(&q[i*4]);
__m256 x1 = x0;
x1 = _mm256_shuffle_ps(x1,x1,0x55);
__m256 x2 = x0;
x2 = _mm256_shuffle_ps(x2,x2,0xAA);
__m256 x3 = x0;
#ifndef NO_PREFETCH
_mm_prefetch((const char*)&q[i*4+8],_MM_HINT_NTA);
#endif
x3 = _mm256_shuffle_ps(x3,x3,0xff);
x0 = _mm256_shuffle_ps(x0,x0,0);
__m256 r0 = _mm256_mul_ps(x0,m0);
__m256 r1 = _mm256_mul_ps(x1,m1);
__m256 r2 = _mm256_mul_ps(x2,m2);
__m256 r3 = _mm256_mul_ps(x3,m3);
__m256 t1 = _mm256_add_ps(r0,r1);
__m256 t2 = _mm256_add_ps(r2,r3);
__m256 t3 = _mm256_add_ps(t1,t2);
_mm256_store_ps(&q[i*4],t3);
}
};
Мораль
Аппаратная поддержка не означает счастья, то же самое скалярное умножение, реализованное вручную (но ценой расхода регистров) оказывается быстрее специализированной инструкции. Непринципиально, около 10% выигрыша, причем как на AVX (256-битные операции), так и на SSE. Да, конечно, у нас не просто два вектора, а матрица на вектор, но разница - в несколько blend.
При этом, 128-битная "эмуляция" SSE4.1-инструкции - требует всего-лишь SSE2, что делает ее еще полезнее.
Comments
А у меня общий вопрос: Вы ведь в курсе, что Win8 будет работ
А у меня общий вопрос: Вы ведь в курсе, что Win8 будет работать и на ARM? А там нет SSE инструкций. Зато есть OpenCL. И на x86 есть OpenCL.
Для Алексовых задач ARM явно не приспособлен. Вот Cell мог б
Для Алексовых задач ARM явно не приспособлен. Вот Cell мог бы, но...
А что за задачи?
А что за задачи?
Дак Вы тред-то почитайте, даже ссылки дадены. Обработка (в
Дак Вы тред-то почитайте, даже ссылки дадены.
Обработка (в том числе потоковая) многопиксельных тяжёлых изображений (условно говоря, 20+ Mpix при 3*16 bit/pixel)
Лёха, я не очень твой таргет переврал? ;)
А, ну про это я в курсе. Изображения интересно было бы обраб
А, ну про это я в курсе. Изображения интересно было бы обрабатывать и на ARM-ах.
Интересно, да. Но эта обработка (если мы говорим о носимом г
Интересно, да. Но эта обработка (если мы говорим о носимом гаджете) должна в такоем случае, по-хорошему, занимать не более 100-200 мс на кадр. То есть, для кадра в 20 Mpix должна быть производительность по крайней мере в 100-200 Mpix/s, что для арма с его контроллером памяти мне кажется (по крайней мере пока) труднодостижимым.
Так как там экранчик отсилы в мегапиксель, то больше оного м
Так как там экранчик отсилы в мегапиксель, то больше оного мегапикселя и обрабатывать не надо. А откуда он взялся, это зум куска кадра или уменьшение существующего - несущественно.
Другой вопрос, что *этот* рынок я не чувствую. Вот PhaseOne выпустили нечто для управления задником с ойпада, пользователи в восторге и так далее, но можно ли туда как-то влезть (и надо ли бежать со всех ног, или рыночное окошко еще долго будет) - я просто не понимаю.
ARM - это же (пока) телефоны и планшеты?
ARM - это же (пока) телефоны и планшеты?
Ну, iPad/Galaxy Tab image processing мог бы быть привлекател
Ну, iPad/Galaxy Tab image processing мог бы быть привлекательным, например
В теории. А на практике там (в ойпаде) такой геморой с полу
В теории.
А на практике там (в ойпаде) такой геморой с получением RAW-файлов с камеры..... Есть Camera Connection Kit, SDK к нему я летом не нашел и наплевал.
Ну это в ойпаде. Рынок вот
Ну это в ойпаде. Рынок вот только что начал заваливаться уже более-менее сносными 10" планшетами на honeycomb. У некоторых есть usb-host. Я вот уже думаю о том, чтобы в отпуск брать что-то типа asus transformer, у которого есит нормальный клавиатурный док с батарейкой, несколько нормальных usb-портов и usb-host. Софт для первичной сортировки RAW'ов на более-менее сносном экране тут бы вполне сгодился. Не то, чтобы очень-очень надо, но бывают моменты когда делать всё равно нечего - почему бы и не?
А вы точно хотите их первично
А вы точно хотите их первично сортировать именно как RAW, а не по JPEG-версиям?
У меня сомнения на эту тему есть, да. На ARM...
В целом, конечно, вариант
В целом, конечно, вариант работы с парным джипегом выглядит заметно более правильным, согласен. Просто никак не могу себя приучить к тому, что флеш больше не нужно экономить. :)
Но это все очень "пока".
Но это все очень "пока".
> А там нет SSE инструкций. Там есть Neon. http://www.arm.c
> А там нет SSE инструкций.
Там есть Neon.
http://www.arm.com/products/processors/technologies/neon.php
ага, и у всех будут тонкие клиенты и вычисления будут на маш
ага, и у всех будут тонкие клиенты и вычисления будут на маштабируемых облаках, на квантовых компьютерах с 50 тысяч миллионов кубитов и кучей йобигерцов и йобибактов памяти.
На ARM есть WMMX и NEON
На ARM есть WMMX и NEON
У меня целевая платформа для процессинга RAW - мощный дескто
У меня целевая платформа для процессинга RAW - мощный десктопный PC и/или мощный ноут.
OpenCL - хорошо, но пока политика - оптимизировать хот-споты, а не переписывать весь код.
А откуда это требование взялось, если не секрет? "Мощный PC
А откуда это требование взялось, если не секрет? "Мощный PC или ноут"?
Ну грубо говоря оттуда, что у (профессионального) фотографа
Ну грубо говоря оттуда, что у (профессионального) фотографа это будет маленькая часть общего бюджета.
Ну т.е. не от хорошей жизни требование такое, да? И тот же ф
Ну т.е. не от хорошей жизни требование такое, да? И тот же фотограф с большим удовольствием возил бы с собой легкий тонкий нетбук или планшет, а не 3-килограмовый ноутбук?
On location (где нетбук или планшет) задачи другие. На нетбу
On location (где нетбук или планшет) задачи другие. На нетбуке-планшете просто нет места для финальной обработки съемки.
То есть там достаточно "95% качества" при приоритете скорости.
А при постпроцессинге нужно "100% качества", многие даже мирятся с непроизводительными ожиданиями в первые секунды - и эти то секунды я и хотел бы убить.
Ну тогда да, еще долгое время самые мощные и распространенны
Ну тогда да, еще долгое время самые мощные и распространенные стационарные и мобильные компы будут на x86 архитектуре.
Но вот что меня гложет: В том же AMD E-350, который 18 ватт ест, встроенный GPU - 80 гигафлопс. Это немало.
Трехкилограммовый-то зачем. У меня ноутбук с i5, 8Gb памяти,
Трехкилограммовый-то зачем. У меня ноутбук с i5, 8Gb памяти, рейдом из SSD и великолепным дисплеем 13" весит всего кило двести (или триста, не помню).
А модель какая?
А модель какая?
Sony Z. Не та, которая только что вышла, а предыдущая, Z1 он
Sony Z. Не та, которая только что вышла, а предыдущая, Z1 она называется что-ли.
Уверен, эти инструкции и используются в OpenCL реализации.
Уверен, эти инструкции и используются в OpenCL реализации.
Хы :) Иронию понял.
Хы :) Иронию понял.
Ну так там, хочется надеяться, и память общая у CPU и OpenCL
Ну так там, хочется надеяться, и память общая у CPU и OpenCL, т.е. можно будет опять оптимизировать хот-споты.
Это да. Я вспомнил наш недавний разговор, и теперь я вижу, ч
Это да. Я вспомнил наш недавний разговор, и теперь я вижу, что для Ваших задач APU действительно могут оказаться очень интересны.
Ага, у меня чешутся руки купить что-то на AMD-шном APU, но п
Ага, у меня чешутся руки купить что-то на AMD-шном APU, но пока не вижу микро-платок (mini-ATX) под него, а micro-ATX поставить некуда.
Тьфу. Micro-ATX поставить некуда, а mini-ITX не вижу в прода
Тьфу. Micro-ATX поставить некуда, а mini-ITX не вижу в продаже.
Не надо гнать в ЖЖ в 7 утра спросонья.
http://www.newegg.com/Product/Product.aspx?Item=N82E16813186
http://www.newegg.com/Product/Product.aspx?Item=N82E16813186212
Да, такие есть, но они какие-то совсем жалкие, как мне кажет
Да, такие есть, но они какие-то совсем жалкие, как мне кажется.
Я хочу старшую модель, которая A-. Если в mini-ITX успешно суют Core2 и прочие Core i5, то и APU этот должен бы залезть.
http://www.newegg.com/Product/Product.aspx?Item=N82E16813157
http://www.newegg.com/Product/Product.aspx?Item=N82E16813157273
А AVX то не блещит
Да, прирост производительности на AVX меньше 15%. И это при том что там легко наступить на грабли и получить performance degradation если какая-нибудь либа вставить SSE инструкцию.
Одно радует, что можно хоть получить заметный прирост производительности за счёт быстрой памяти и высокой частоты проца. Думаю на твоей задаче, которая O(n), скорость памяти важней всего. Интересно посмотреть действительно ли поднятие частоты памяти дает прирост.
Так же в свое время я пытался понять, как писать код чтобы воспользоватся преимуществами Dual-channel и Triple-channel памяти, но прироста не наблюдал... В системнике то вставлял планки, то вытаскивал.
Я так для себя понял, что AVX
Я так для себя понял, что AVX - это тот же dual issue SSE, только поставленный в ряд.
Вместе с тем, если генерировать SSE-код из тех же макросов (а не AVX), то скорость получается заметно ниже и начинает зависеть от компилятора. Скажем, для _load1 без префетча и компилятора intel - 316Mpix вместо 527 (c префетчем - возвращается).
Т.е. граблей тут густо разложено.
А оно реально надо? Ну то есть 500 vs 600 vs 700? Все одно,
А оно реально надо? Ну то есть 500 vs 600 vs 700? Все одно, через года через полтора-три оно удвоится/учетверится, в кэш влезет вообще вся картинка и оно достигнет статуса "да пофиг, все достаточно быстро".
PS: Вспоминая mp3/mpeg1 на 486, где декодер оного действительно в проц упирался, но с появлением P/PII проблема рассосалась сама собой.
Сейчас "пофиг, достаточно быстро" (т.е. ~25 кадров/сек) дост
Сейчас "пофиг, достаточно быстро" (т.е. ~25 кадров/сек) достигается только для экранного разрешения в 2-4 мегапикселя и без качественной демозаики. А с демозаикой - в лучшем случае окошко "100%" размером 500x500.
То есть *сейчас*, если не ждать несколько лет, делать таки что-то надо.
А упражнения ради очередных 50 или 100Mpix/sec - это, конечно, чисто для воскресного вечера.
Не говоря о том, что не у всех юзеров Core i7 @4.5Ghz, а есл
Не говоря о том, что не у всех юзеров Core i7 @4.5Ghz, а если целиться еще и в машину 4-летней давности, как мой ноут (Core2 T7500), то там еще чуть не на порядок все медленнее.
Я вот почесал репу еще. Что-то у меня сомнения, что оно удво
Я вот почесал репу еще.
Что-то у меня сомнения, что оно удвоится-учетверится на одном потоке на существующей однопоточной codebase.
Так это, а у твоей целевой аудитории разве не по 4+ ядра в т
Так это, а у твоей целевой аудитории разве не по 4+ ядра в тачке стоит? То есть достаточно, чтобы один поток мог использовать где-то четверть псп памяти и дальше в общем-то все равно. А задача вроде как параллелится только в путь.
PS: Ты на C-blocks смотрел?
Оно не все так радужно, то есть 4 потока не дают учетверения
Оно не все так радужно, то есть 4 потока не дают учетверения. Где-то двухсполовинивание, причем я именно о С-шном коде, который в память не уперт.
Ну а дальше правило Амдала тоже серьезно начинает мешать.
Правильно, но если взять SSEчто-то там версию, и упремся в п
Правильно, но если взять SSEчто-то там версию, и упремся в память, то там уже все эти законы перестанут действовать, то есть дальше оптимизировать бессмысленно. Осталось только в память упереться, впрочем ты как раз и изучаешь, как это сделать.
Мне-то интересно, насколько реален такой сценарий в ближайшем будущем.