Не могу молчать:
Есть такие вот "ассемблерные" макросы:
- _mm_store_ps(указатель, XMM-регистр) - писать в память.
- _mm_stream_ps(те же параметры) - писать в память мимо кэша.
Для первого из них генерируется инструкция movaps (Intel C++ в некоторых условиях генерирует movntps, чему я удивлялся всегда). Для второго - всегда movntps ("писать мимо кэша"). В теории, при обработке больших потоков данных вторая быстрее.
Я неопытный сварщик SSE-ассемблером занялся не так давно, на рабочей станции был уже Core I7 и на Core2 я свои изделия (которые пока для internal use) - не запускал почти. А тут - запустил. Удивился тормозам. Помикробенчмаркал. На коротком цикле, вроде поминаемых тут скалярных умножений, получил разницу в четыре раза.
В том смысле, что movntps - в 4 раза медленнее. 40 мегапикселей вместо 160. Устойчиво, от компилятора не зависит, и на gcc так и на Clang.
В-принципе, от mm_stream выигрыша большого на i7 не было. Похоже, лучше про нее вообще забыть.
Comments
А что удивительного ?
Сам интел пишет, что записи, ининциируемы movntps исользуют WC-протокол, т.е кешируются только во write-буферах процессора. Поскольку буферов единицы (максимум десятки) штук, записи, после заполнения имеющихся буферов, начинают выполнятся на скорости памяти. Буферы имеют размер строки кеша, так то срабатывает C (combining) и запись идет все-таки быстрее чем совсем медленная память, но медленнее, чем в кеш.
У меня данных - 1.6Gb,
У меня данных - 1.6Gb, поэтому кэш уже несущественен.
На i7 movntps (для больших объемов) был заметно быстрее, на i7-AVX я не вижу большой разницы, на Core2 - медленнее и сильно.
Чудеса.
Могу поугадывать. Если
Могу поугадывать.
Если тестовым примером был код из http://blog.lexa.ru/2011/09/01/o_kompilyatorakh_i_protsessorakh.html, то хочу обратить внимание, что тут производится кешируемое чтение по тем же страницам, по которым идет WC-запись. Интел называет это неопределенным поведением и требует обязательно использовать как минимум store fence вокруг WC-записей.
Мое предположение состоит в том, что self-snoop на core i7 и старше замечает, что строка уже в кеше, а на старых Core2 нет.
Даже на терабайтных записях кеш помогает за счет более гибкого write coalescing. Писатели драйверов видеокарт давно знают, что линейная запись текстуры в основной памяти и ремап в апертуру в разы быстрее записи через WC-апертуру.
Ну так чтение происходит *до*
Ну так чтение происходит *до* записи, после записи - по тому же адресу ничего не читается.
История обсуждается вот тут в комментариях: http://blog.lexa.ru/2010/12/21/polna_chudes_moguchaya_priroda.html
Это примерно тот же самый код по смыслу: прочитали 4 float, что-то посчитали, записали в то же место.
И на i7-920 у меня получалось, что movntps для записи - заметно быстрее, чем movaps. Для i7-avx принципиальной разницы я не вижу.
Я именно об этом и говорю -
Я именно об этом и говорю - строка уже в кеше, и процессор может, но не обязан, это заметить. В любом случае, код некорректен из-за отсутствия fence, и все это мои спекуляции.
Про fence я не понимаю. 1)
Про fence я не понимаю.
1) Порядок, гарантированно, чтение - обработка - запись. Поэтому никакая сериализация (за исключением конца цикла) не нужна.
2) Столь же гарантированно, если я вдруг чего пишу через movntps по адресу Х, то по адресу Х+16 ничего *самопроизвольно* писаться не будет (иначе бы вся эта write-combining memory все бы разваливала нахрен если такая запись как-то происходит без учета состояния кэшей).
Так зачем fence?
Если бы обработка была "чтение по адресу Х, обработка, запись по адресу Х+1" - тогда я понимаю. Но обработанный (прочитанный-обработанный-записанный) элемент данных - не трогается.
BTW, в каких-то ситуациях intel сам лепит movntps без (m|l|s)fence
Я пробовал как то _mm_stream_ps на Core2Duo. Медленнее, чем
Я пробовал как то _mm_stream_ps на Core2Duo. Медленнее, чем обычный store. Тоже не понял, в чем же фокус.
Моя гипотеза - вымывается кэш. Поэтому чисто write (залить
Моя гипотеза - вымывается кэш.
Поэтому чисто write (залить память константой) должно быть быстро, а read-write - медленно.
Сейчас попробую.
MOVNTPS нужно использовать только для тех участков памяти, к
MOVNTPS нужно использовать только для тех участков памяти, которые не читаются в кэш. Если данные в кэше, прироста в скорости он не даст
Мои измерения показывают другое: http://alextutubalin.livejo
Мои измерения показывают другое: http://alextutubalin.livejournal.com/253179.html
Post new comment