Свежие комментарии

Title Comment
а зачем нужно столько ядер на выгребание? у линуха ведь есть

а зачем нужно столько ядер на выгребание? у линуха ведь есть расштрения всякие типа zero copy.

Если сравнивать различные поколения ускорителей, то да, объе

Если сравнивать различные поколения ускорителей, то да, объем быстрой памяти на один вычислительный блок растет. Но что с того? В 2 раза за 4 года - это не так уж и много.

Ну и вот еще что, вернусь к одной Вашей фразе несколькими комментариями выше:

> Для алгоритмов, у которых отношение flops/memory небольшое и не растет с размером задачи - вы для внешних GPU окажетесь ограничены PCIe bandwidth

Это верно лишь в случае, если данные для работы ядра необходимо передать из хоста в устройство. Что совершенно не обязательно.

Ну "относительно" же. 8800GTX - 16kb shared, 32kb регистров

Ну "относительно" же.

8800GTX - 16kb shared, 32kb регистров (8k по 4 байта) на SM, всего 48kb быстрой памяти.
Fermi: 48k shared, 16k L1, 128k регистров. Всего 192kb на SM.

Да, SM тоже подрос, поэтому оно не учетверилось в расчете на единицу SIMD, а удвоилось. С точки зрения блочных алгоритмов - часть утроилась (shared), а часть - удвоилась (регистры).

Это за 4 года, с 2006 по 2010.

Согласен почти со всем. Не согласен с последним. Локальная п

Согласен почти со всем. Не согласен с последним. Локальная память/L1 - это дорого. В сумме сейчас в районе 64КБ на один compute unit. Думаете, если бы у производителей была возможность ее увеличить сравнительно недорого, они бы этого не сделали?

Да, все так, но не все так плохо :) Для алгоритмов, у котор

Да, все так, но не все так плохо :)

Для алгоритмов, у которых отношение flops/memory небольшое и не растет с размером задачи - вы для внешних GPU окажетесь ограничены PCIe bandwidth. А для внутренних - memory bandwidth (которая в разы больше).

А если flops/mem растет с размером локального блока вычислений (как для dgemm, к примеру), то нагрузка на память уменьшается путем увеличения local/shared mem, что относительно недорого для производителей GPU/APU.

APU архитектура сбалансирована только для слабых интегрирова

APU архитектура сбалансирована только для слабых интегрированных GPU. Потому как более мощным GPU будет не хватать пропускной способности глобальной памяти, которая, в случае интеграции GPU и CPU - это обычная RAM. Вон, в 7xxx серии будет память XDR2 с 256-битной шиной с пропускной способностью под 300 ГБ/с. Такой пропускной способности у обычной RAM (DDR3) нет.

Но, кстати, конструкция Бульдозер+GPU в одном флаконе (т.е.

Но, кстати, конструкция Бульдозер+GPU в одном флаконе (т.е. APU, как они их называют) - для вычислений опять несбалансирована, потому что на I/O ничего тратить не надо.
Ну да она и для недорогих десктопов, с другой стороны.

А по вопросу: Из новости на ФЦентре: "По сведению аналитико

А по вопросу:

Из новости на ФЦентре: "По сведению аналитиков компании IDC, доля AMD на рынке процессоров для серверов снизилась со второго квартала 2006 года с 25,9 % до 5,5 % во втором квартале 2011 года".

А, ага. Да, софт придется делать, это не вопрос. Именно при

А, ага.

Да, софт придется делать, это не вопрос. Именно придется, потому что гетерогенные архитектуры - это неизбежное ближайшее будущее, да и настоящее уже, что уж там.

Ну так я о том и пишу там выше - для гибридной конструкции б

Ну так я о том и пишу там выше - для гибридной конструкции бульдозер получается примерно в самый раз.
Но имеющийся софт, который задачи по ядрам распределяет "как-то", придется допиливать.

> Но на эти два GPU - надо 6 ядер на I/O, четырех мало. Пус

> Но на эти два GPU - надо 6 ядер на I/O, четырех мало.

Пусть так. Но этим ядрам не особо то и нужны FPU, верно?

Оно как бы и да и нет, в смысле ускорителей. Матрицы перемно

Оно как бы и да и нет, в смысле ускорителей. Матрицы перемножать - да, два GPU 6-тысячной серии раз в 6-7 быстрее, чем два 12-ядерных оптерона. И дешевле раза в четыре (6990 - 25k, оптерон 6176 - 45k, если я ничего не перепутал).
Но на эти два GPU - надо 6 ядер на I/O, четырех мало.

А как только начинаются ветвления, так сразу все не так однозначно.
Да и там где однозначно - может оказаться, что реализаций просто нет. Вот скажем для линпака - dgemm для Multi-GPU есть, а dtrsm - я нашел только single-GPU.

Я вот думаю, что тут расчет у AMD простой: Матрицы перемножа

Я вот думаю, что тут расчет у AMD простой: Матрицы перемножать в больших количествах - это на ускорителях (скоро уже и 7xxx серия подоспеет с 2,000 ядрами). А SQL-серверу, web-серверу FPU (практически) не нужен. В последнем абзаце статьи по ссылке об этом как раз упоминается.

Про fence я не понимаю. 1)

Про fence я не понимаю.
1) Порядок, гарантированно, чтение - обработка - запись. Поэтому никакая сериализация (за исключением конца цикла) не нужна.
2) Столь же гарантированно, если я вдруг чего пишу через movntps по адресу Х, то по адресу Х+16 ничего *самопроизвольно* писаться не будет (иначе бы вся эта write-combining memory все бы разваливала нахрен если такая запись как-то происходит без учета состояния кэшей).

Так зачем fence?

Если бы обработка была "чтение по адресу Х, обработка, запись по адресу Х+1" - тогда я понимаю. Но обработанный (прочитанный-обработанный-записанный) элемент данных - не трогается.

BTW, в каких-то ситуациях intel сам лепит movntps без (m|l|s)fence

Я именно об этом и говорю -

Я именно об этом и говорю - строка уже в кеше, и процессор может, но не обязан, это заметить. В любом случае, код некорректен из-за отсутствия fence, и все это мои спекуляции.

Моя гипотеза - вымывается кэш. Поэтому чисто write (залить

Моя гипотеза - вымывается кэш.

Поэтому чисто write (залить память константой) должно быть быстро, а read-write - медленно.

Сейчас попробую.

Ну так чтение происходит *до*

Ну так чтение происходит *до* записи, после записи - по тому же адресу ничего не читается.

История обсуждается вот тут в комментариях: http://blog.lexa.ru/2010/12/21/polna_chudes_moguchaya_priroda.html
Это примерно тот же самый код по смыслу: прочитали 4 float, что-то посчитали, записали в то же место.

И на i7-920 у меня получалось, что movntps для записи - заметно быстрее, чем movaps. Для i7-avx принципиальной разницы я не вижу.

Я пробовал как то _mm_stream_ps на Core2Duo. Медленнее, чем

Я пробовал как то _mm_stream_ps на Core2Duo. Медленнее, чем обычный store. Тоже не понял, в чем же фокус.

Могу поугадывать. Если

Могу поугадывать.

Если тестовым примером был код из http://blog.lexa.ru/2011/09/01/o_kompilyatorakh_i_protsessorakh.html, то хочу обратить внимание, что тут производится кешируемое чтение по тем же страницам, по которым идет WC-запись. Интел называет это неопределенным поведением и требует обязательно использовать как минимум store fence вокруг WC-записей.

Мое предположение состоит в том, что self-snoop на core i7 и старше замечает, что строка уже в кеше, а на старых Core2 нет.

Даже на терабайтных записях кеш помогает за счет более гибкого write coalescing. Писатели драйверов видеокарт давно знают, что линейная запись текстуры в основной памяти и ремап в апертуру в разы быстрее записи через WC-апертуру.

Лучшая система

На сегодняшний момент Windows7 одна из лучших систем в мире. Это наверное самый удачный продукт, который выпустила компания Microsoft за многие годы. Vista изначально была обречена на неудачу, даже ее разработчики признали, что это мертвая система, у которой нет будущего. Многие пытаются сравнивать две системы Vesta и Windows7 это не правильно, внешнее сходство ни о чем не говорит. Это абсолютно разные системы и по интерфейсу, и по надежности, и по скорости работы!

В реальном мире оно как-то без шансов.

В реальном мире оно как-то без шансов.

> А значит - писать таки на SIMD-ассемблере. А не проще ли

> А значит - писать таки на SIMD-ассемблере.

А не проще ли предупредить в ридми о наличии фигни и рекомендовать оптимальный компилятор?

У меня данных - 1.6Gb,

У меня данных - 1.6Gb, поэтому кэш уже несущественен.

На i7 movntps (для больших объемов) был заметно быстрее, на i7-AVX я не вижу большой разницы, на Core2 - медленнее и сильно.

Чудеса.

А что удивительного ?

Сам интел пишет, что записи, ининциируемы movntps исользуют WC-протокол, т.е кешируются только во write-буферах процессора. Поскольку буферов единицы (максимум десятки) штук, записи, после заполнения имеющихся буферов, начинают выполнятся на скорости памяти. Буферы имеют размер строки кеша, так то срабатывает C (combining) и запись идет все-таки быстрее чем совсем медленная память, но медленнее, чем в кеш.

На моём i7 2670QM (2GHz) этот код выдаёт 475 MPix/sec если д

На моём i7 2670QM (2GHz) этот код выдаёт 475 MPix/sec если данные в L2, 450 MPix/sec если данные в L3, и 310 MPix/sec если данные в памяти

SECTION .rdata
align 32
table0 dd 0.44, 0.33, 0.22, 0.11, 0.44, 0.33, 0.22, 0.11
table1 dd 0.88, 0.77, 0.66, 0.55, 0.88, 0.77, 0.66, 0.55
table2 dd 1.04, 1.03, 1.02, 1.01, 1.04, 1.03, 1.02, 1.01

SECTION .text

global convert_pixels

; extern "C" void convert_pixels(const float* source, float* destination, size_t length)
convert_pixels:
; rcx - source
; rdx - destination
; r8 - length

vzeroupper
align 32
.main_processing_loop:
vmovaps ymm0, [rcx]
vmovaps ymm1, [rcx + 32]
vmovaps ymm2, [rcx + 64]
vmovaps ymm3, [rcx + 96]

vmulps ymm4, ymm0, [table0]
vmulps ymm5, ymm0, [table1]
vmulps ymm6, ymm0, [table2]
vmulps ymm7, ymm1, [table0]
vmulps ymm8, ymm1, [table1]
vmulps ymm9, ymm1, [table2]
vmulps ymm10, ymm2, [table0]
vmulps ymm11, ymm2, [table1]
vmulps ymm12, ymm2, [table2]
vmulps ymm13, ymm3, [table0]
vmulps ymm14, ymm3, [table1]
vmulps ymm15, ymm3, [table2]

vhaddps ymm4, ymm4, ymm5
vhaddps ymm6, ymm6, ymm7
vhaddps ymm8, ymm8, ymm9
vhaddps ymm10, ymm10, ymm11
vhaddps ymm12, ymm12, ymm13
vhaddps ymm14, ymm14, ymm15

vhaddps ymm4, ymm4, ymm6
vhaddps ymm8, ymm8, ymm10
vhaddps ymm12, ymm12, ymm14

vmovaps [rdx], ymm4
vmovaps [rdx + 32], ymm8
vmovaps [rdx + 64], ymm12
sub rcx, -128
add rdx, 96
sub r8, 32
jnz .main_processing_loop
vzeroupper

ret

Заврался я совсем sse4.1 на

Заврался я совсем sse4.1 на core2 не было. Это был i5.

Да, именно это я и

Да, именно это я и предпологал. Писал я генератор псевдослучайных floats и там как раз скалярное произведение. Обрадовался я, и побежал sse4.1 использовать, а на практике оказалось на 15% медленее вручную прописанных mult_ps, add_ps. Но это на core2 было, подумал я что на i7 могли уже допилить до ума. А нет...

В таком духе можно и 256bit вариант написать. Должен быть самый быстрый.

Вот так вот можно: __m128 x0

Вот так вот можно:

__m128 x0 = _mm_broadcast_ss(&q[i*4]);
__m128 x1 = _mm_broadcast_ss(&q[i*4+1]);
__m128 x2 = _mm_broadcast_ss(&q[i*4+2]);
__m128 x3 = _mm_broadcast_ss(&q[i*4+3]);
__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_stream_ps(&q[i*4],t3);

Получается быстрее, чем через dpps (что прикольно, инструкций то больше, да и broadcast этот...), но медленнее чем dpps+avx.

Сделал:

Сделал: http://blog.lexa.ru/2011/09/04/o_kompilyatorakh_i_protsessorakh_avx.html

Ну так а мне, по счастью, и не надо 256 бит за раз, у меня с

Ну так а мне, по счастью, и не надо 256 бит за раз, у меня скалярное умножение двух векторов длиной 4
И _mm256_dp_ps() делает именно это - умножает зараз две половинки.

Pages

Subscribe to comments_recent_new