Одной строкой
lexa - 14/Фев/2017 19:43
Вот эта вот гадость: Трудовые будни или еще раз о формате DNG
Починена вот тут: FastRawViewer 1.3.9 beta (билд 1051)
Вот эта вот гадость: Трудовые будни или еще раз о формате DNG
Починена вот тут: FastRawViewer 1.3.9 beta (билд 1051)
(C)opyright 2006-2024, Alex Tutubalin, lexa@lexa.ru
Comments
А можно тебя помучать про SIMD?
Я тут пытаюсь нащупать лучший способ сделать из массива байтов (т.е. целых чисел в диапазоне [0..255]) массив float'ов (32-ъх битных IEEE754) в диапазоне [-1.0..1.0] — т.е. с рескейлом и сдвигом. Смотрю я на варианты «что угодно», SSE4 (ведь нет уже живого железа без него? SSE3 это первый Core!), AVX1, AVX2+FMA (потому что, кажется, AVX2 без FMA3 не бывает). Смотрю на SkyLake (i7-6700K зажатый ровно на 40, что бы никакие трубобусты мне бенчмарки не пачкали). А, да, gcc 6.3.0 и clang 3.9.1 дают качественно одинаковые результаты. И нахожусь в некотором недоумении.
(1) Если разрешить -mavx2 -mfma3, то код писать вообще не надо. В смысле, тупой цикл по 1 элементу зараз на plain С с одним умножением и одним вычитанием даёт чуть больше 9G в секунду на 4GHz проце. Компилятор развернул и векторизовал ВСЁ. Я не смог написать руками лучше, хотя пытался раз 5. Мой лучший ручной результат с AVX2 — 8G в секунду.
(2) А со всем остальным лучше всего справляется ручной код не лезущий дальше SSE2. Ну, простенький, несколько анпэков, конверт, мул-суб, всё.
Что меня удивляет (кроме ума компилятора): что, например, с AVX всё равно лучше SSE2. Т.е. пока у нас нет FMA и, главное, _mm256_unpack{hi|lo}_epi{8|16}, от 256-битных регистров тут толку нет.
Это я что-то не так делаю? Ну не верю я, что такая типовая на вид задача не может выиграть от AVX, только от AVX2 :)
И, кстати, какова твоя статистика (есть ли она у тебя) с какого SSE можно начинать что бы уже никого по сути не обидеть?
"что, например, с AVX всё
vzeroupper делается? Там переход AVX/SSE очень дорогой (без явного обнуления), т.е. ради пары инструкций оно того не стоит.
Ну и второй вопрос, а вот если входных значений всего 256, то таблица не быстрее?
vzeroupper не делается, но
vzeroupper не делается, но там вообще распаковка адовая получается:
const __m128i mem0 = _mm_load_si128((__m128i*)from);
const __m128i tmp16l = _mm_unpacklo_epi8(mem0, zero);
const __m128i tmp16h = _mm_unpackhi_epi8(mem0, zero);
const __m128i tmp32ll = _mm_unpacklo_epi16(tmp16l, zero);
const __m128i tmp32hl = _mm_unpackhi_epi16(tmp16l, zero);
const __m128i tmp32lh = _mm_unpacklo_epi16(tmp16h, zero);
const __m128i tmp32hh = _mm_unpackhi_epi16(tmp16h, zero);
const __m256i tmp0 = _mm256_insertf128_si256(zero256, tmp32ll, 0);
const __m256i tmp1 = _mm256_insertf128_si256(zero256, tmp32lh, 0);
const __m256 in0 = _mm256_castsi256_ps(_mm256_insertf128_si256(tmp0, tmp32hl, 1));
const __m256 in1 = _mm256_castsi256_ps(_mm256_insertf128_si256(tmp1, tmp32hh, 1));
const __m256 out0 = _mm256_sub_ps(_mm256_mul_ps(in0, mul), del);
const __m256 out1 = _mm256_sub_ps(_mm256_mul_ps(in1, mul), del);
/* Store 16 floats */
_mm256_store_ps(to, out0);
_mm256_store_ps(to + 8, out1);
count -= 16;
from += 16;
to += 16;
Куда его тут? Да, я ещё интерливинг пытался тут вставить (ну типа как половина данных готова так с ними и работать а не групировать операции по смыслу как я тут скопипастил) и удвоить объём работы в одном проходе цикла (тоже как с группировкой по смыслу так и сгруппировкой по локальности данных) и то и другое даёт изменнеия в пределах статпогрещности. Да, в этом коде zero, zero256, mul, del — константы, понятно. Нули, множитель (512/255) и просто 1 в соотвествующих веторах.
Таблица! Это было первое, что я попытался сделать. Это медленней в 2-3 раза чем следующий самый медленный вариант!
А вот ключи у компилятора
А вот ключи у компилятора какие, там _mm_unpacklo_epi16 (к примеру) транслируется в VPUNPCKLWD или без V?
если без, то вот и этот самый микс.
Вообще, я не понимаю зачем читать-распаковывать по 128 бит, а потом сливать в 256. Кто не дает сразу 256?
И, кстати, 9G/sec - это в каких единицах, входной поток или выходной?
Сразу в 256 бит распаковывать
Сразу в 256 бит распаковывать можно только в AVX2 (_mm256_unpack{hi|lo}_epi{8|16}()) — или я не понимаю как. Если подскажешь буду благодарен.
ключи для avx "-O3 -mfpmath=sse -ffast-math -mavx" и код с v в начале, да:
3c: c5 e9 60 c4 vpunpcklbw %xmm4,%xmm2,%xmm0
40: c5 e9 68 d4 vpunpckhbw %xmm4,%xmm2,%xmm2
44: c5 f9 61 cb vpunpcklwd %xmm3,%xmm0,%xmm1
48: c5 f9 69 fb vpunpckhwd %xmm3,%xmm0,%xmm7
4c: c5 e9 61 c3 vpunpcklwd %xmm3,%xmm2,%xmm0
50: c5 e9 69 d3 vpunpckhwd %xmm3,%xmm2,%xmm2
54: c4 e3 75 18 cf 01 vinsertf128 $0x1,%xmm7,%ymm1,%ymm1
5a: c4 e3 7d 18 c2 01 vinsertf128 $0x1,%xmm2,%ymm0,%ymm0
9G/sec это семплы. Т.е. 9G байтов переаботано в 9G флоатов (36G байтов, соотвественно).
Ну от 36GB/sec out + 9GB/sec
Ну от 36GB/sec out + 9GB/sec in - это, поди, память насытилась уже, больше нету?
Во всяком случае похоже же, у меня DDR4-3200 вот в районе 45Gb/sec вроде и есть.
stream_ps() вместо store_ps() может несколько ускорить.
Ну, у меня всё в кэш лезет.
Ну, у меня всё в кэш лезет. Мегабайт байтов, соответственно 4 мегабайта флотов, по кругу. Если я побольше данных сделаю всё в DDR4-2400 упрётся (да, я не так богат что бы 3200), это понятно.
Это-та скорость меня устраивает, вопрос как из AVX простого выжать похожее.
(3200 и 2400 стоят сейчас
(3200 и 2400 стоят сейчас одинаково).
Если в кэш, то не надо stream_ps.
Когда я покупал разница на 8G
Когда я покупал разница на 8G модули была раза в полтора! 3200 все уже считались оверклокерскими, с радиаторами, красивой упаковкой, такое.
Сейчас память подорожала
Сейчас память подорожала заметно (смотрел цену на DDR3 - процентов на 30-40) и похоже что дешевая быстрее.
Т.е. 4x16 не только с радиатором, но и кулером отдельным - стоила ну в пределах 10% разницы относительно 2400 приличного производителя (т.е. не хрен с горы неясный, а там Samsung/crucial и прочие подобные слова). Ну то есть это конкретный корсар на самом деле был дешевым, потому что можно было найти и еще подороже раза в полтора.
А вообще, вот у тебя в случае
А вообще, вот у тебя в случае AVX+SSE (относительно SSE)
- две лишних упаковки
- но зато ты sub/mul делаешь с длинными векторами т.е. два действия вместо четырех.
Поди, одно аккурат стоит другого, два действия поэкономил, два добавил?
Вот Агнер наш Фог пишет, что
Вот Агнер наш Фог пишет, что insertf128 - вообще два такта. А sub/mul - по одному, вестимо.
Да, похоже на то. Интересно,
Да, похоже на то. Интересно, можно ли упаковать в AVX лучше, чем написал...
Ну и на минуточку, а где
Ну и на минуточку, а где собственно преобразование int-float?
Тааак, это я накопипастил
Тааак, это я накопипастил криво, из варианта с битовой магией вместо castsi256(). Не то, короче, скопипастил. И, кажется, померял какую-то лажу. Ща буду перемеривать. Хотя битовая магия вообще ничего не даёт, никакого выигрыша против castsi256
Я про cast вообще не понял.
Я про cast вообще не понял.
Или битовая магия (cast + sub), или cvttps_epi32
А одного каста - мало ж.
Именно этот код (не повезло
Именно этот код (не повезло ему) был вообще неправильным. Я перемерял правильно, с cvt, и результаты с точностью до статпогрешности те же. Ничего конверсия не стоит, не в ней дело.
А битовая магия выглядит так же только там вместо старших нулей всё пакуется константой 0x4700 во-первых и множитель другой во-вторых. Т.е. с точки зрения паковки и mul-sub всё в точногсти так же, только константы другие (и каст вместо конверсии).
И ещё про AVX. Оказывается,
И ещё про AVX. Оказывается, по крайней мере у Зионов, AVX не только здорово ограничивает частоту турбобуста (https://www.microway.com/knowledge-center-articles/detailed-specificatio...) но и тактуется отдельно (таблица три тут http://www.intel.com/content/dam/www/public/us/en/documents/specificatio...) заметно медленней базовой частоты из спецификации процессора.
Для меня это вот новость. Интересно, что у i3/i5/i7?
По мне, из таблиц не следует,
По мне, из таблиц не следует, что блоки AVX тактуются отдельно.
Я долго спорил с человеком,
Я долго спорил с человеком, показавшим мне эти ссылки (_slw), но он меня убедил, что заголовок таблички 3 в PDF («Intel AVX Core frequency (GHz)») сложно интерпритировать по другому. AVX Core как ещё понять? И числа там уж совсем низкие относительно частоты в спецификации.
А что такое "Intel® AVX Turbo
А что такое "Intel® AVX Turbo Boost Technology Maximum Core Frequency" (более правые столбцы в той же табличке)?
До скольки турбобуст
До скольки турбобуст разгоняет. Но вообще, да, тоже аргумент. Мутные формулировки.
Но AVX heavy, кстати (Prime95
Но AVX heavy, кстати (Prime95, маленьким FFT) жрет ватты как не в себе, это вот факт.
AVX Typical (Handbrake, Linpack AVX-овый) - сильно меньше.
Собственно, вот на Анандтехе
Собственно, вот на Анандтехе (внизу страницы): http://www.anandtech.com/show/8423/intel-xeon-e5-version-3-up-to-18-hasw...
И у Интела разжевано: http://www.intel.com/content/dam/www/public/us/en/documents/white-papers...
AVX base - гарантированная. AVX Turbo - как пойдет, в зависимости от нагрева.
Частоты таки общие для всего горшка.
О, вот вторая ссылка, да,
О, вот вторая ссылка, да, однозначно отвечает.
Значит у i7 (7xxx) жизнь
Значит у i7 (7xxx) жизнь устроена, насколько я вижу, так
- стандартные настройки (без разгона) с AVX оно идет до базовой частоты, а не до турбы. Впрочем, я в этом режиме особо не гонял.
- разгон: можно задать "AVX offset" т.е. понижение множителя (от максимального турбо) если используется AVX
Ну и Агнера Фога читаем: "разогрев" AVX-модуля на Skylake (про Kabu Lake еще не написал) занимает 56 тысяч что ли тактов, дохрена. Остывает (отключается) тоже сильно не сразу, т.е. вообще рекомендуется pre-heat если возможно :)
56 тысяч тактов! Оу.
56 тысяч тактов! Оу.
Читайте Агнера нашего Фога,
Читайте Агнера нашего Фога, мудрость великая в его PDF-ках