Skip to Content

Одной строкой: mov[a|nt]ps

Не могу молчать:

Есть такие вот "ассемблерные" макросы:

  • _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 нужно использовать только для тех участков памяти, которые не читаются в кэш. Если данные в кэше, прироста в скорости он не даст

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <s> <i> <b> <blockquote>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <ruby>. The supported tag styles are: <foo>, [foo].
  • Images can be added to this post.

More information about formatting options



.