2013-06-26 6 views
8

Я сделал тест с этимКогда программа выиграет от предварительной загрузки и невременной загрузки/хранения?

for (i32 i = 0; i < 0x800000; ++i) 
    { 
     // Hopefully this can disable hardware prefetch 
     i32 k = (i * 997 & 0x7FFFFF) * 0x40; 

     _mm_prefetch(data + ((i + 1) * 997 & 0x7FFFFF) * 0x40, _MM_HINT_NTA); 

     for (i32 j = 0; j < 0x40; j += 0x10) 
     { 
      //__m128 v = _mm_castsi128_ps(_mm_stream_load_si128((__m128i *)(data + k + j))); 
      __m128 v = _mm_load_ps((float *)(data + k + j)); 

      a_single_chain_computation 

      //_mm_stream_ps((float *)(data2 + k + j), v); 
      _mm_store_ps((float *)(data2 + k + j), v); 
     } 
    } 

Результаты странные.

  1. Независимо от того, сколько времени занимает a_single_chain_computation, латентность нагрузки не скрыта.
  2. И, кроме того, дополнительное суммарное время увеличивается, когда я добавляю больше вычислений. (С одним v = _mm_mul_ps(v, v) предварительная выборка сохраняет около 0,60 - 0,57 = 0,03 с. И с 16 v = _mm_mul_ps(v, v) она экономит около 1,1 - 0,75 = 0,35 с. ПОЧЕМУ?)
  3. Невременная загрузка/хранение ухудшает производительность с предварительной выборкой или без нее. (Я понимаю, часть нагрузки, но почему магазины тоже?)
+0

Вы пробовали обычную предварительную выборку? По моему опыту, у меня никогда не было хорошего варианта использования для невременных нагрузок. Но я обнаружил, что потоковые хранилища полезны при выполнении абсолютно случайных записей в идеально выровненных блоках размера кешины. – Mysticial

+0

@Mysticial '_MM_HINT_NTA' описывается как« минимизация загрязнения кэша », предполагая, что он не является временным. Но _MM_HINT_Tx, похоже, не ухудшает производительность. Угадайте, потому что нет другого использования кеша. – BlueWanderer

+0

Я бы не ожидал, что '_MM_HINT_Tx' ухудшит производительность. В случае невременной предварительной выборки, кажется, саморазрушится, чтобы предварительно извлечь что-то и не загрязнять кеш. Поскольку цель предварительной выборки - это привести ее в кеш. Это одна из вещей, которые я действительно никогда не понимал. :) – Mysticial

ответ

5

Вы должны отделить две разные вещи здесь (которые, к сожалению, имеют похожее название):

  • Non-височной упреждающая выборка - Это будет предварительная выборка строки, но напишите ее как наименее недавно использованную, когда она заполняет кеши, поэтому она будет первой в очереди на выселение, когда вы будете использовать тот же набор. Это оставляет вам достаточно времени, чтобы на самом деле использовать его (если вам не очень повезло), но не будет тратить больше, чем единственный выход из этого набора, поскольку следующая предварительная выборка просто заменит его. Кстати, в отношении ваших комментариев выше - каждая предварительная выборка будет загрязнять кеш-память L3, она включена, поэтому вы не сможете обойтись без нее.

  • Невременные (потоковые) нагрузки/хранилища - это также не загрязняет кеши, а использует совершенно другой механизм их неразрушаемости (а также комбинирования записи). Это действительно будет иметь штраф за производительность , даже если вам действительно не нужны эти строки снова, так как кэшируемая запись имеет роскошь оставаться в буфере в кеше до выселения, поэтому вам не нужно записывать ее правильно далеко. Если вы несовместимы с вами, и в некоторых сценариях это может помешать вашему mem BW. С другой стороны, вы получаете выгоду от объединения писем и слабого упорядочения, что может дать вам некоторое преимущество - это несколько случаев. Суть здесь в том, что вы должны использовать его только тогда, когда он помогает, не предполагают его волшебно повышает производительность (Nothing делает это в настоящее время ..)

Что касается ваших вопросов -

  1. ваш prefetching должен работать, но это не достаточно рано, чтобы повлиять. попробуйте заменить i+1 на большее количество. На самом деле, может быть, даже сделать развертку, было бы интересно посмотреть, сколько элементов вы должны заглянуть.

  2. я предположил бы, что это так же, как 1 - с 16 мулов вашей итерации достаточно долго для упреждающей работы

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

0

Если вычисление цепи очень мало, и если вы читаете последовательно памяти, то процессор будет упреждающий хорошо само по себе, и на самом деле работает быстрее, так как его декодер имеет меньше работы.

Потоковые нагрузки и магазины хороши только в том случае, если вы не планируете получать доступ к этой памяти в ближайшем будущем. Они в основном предназначены для памяти без обратной записи (WB), которая обычно обнаруживается при работе с графическими поверхностями. Явное префектирование может хорошо работать на одной архитектуре (модели ЦП) и отрицательно влиять на другие модели, поэтому при оптимизации их использовать в качестве последней опции.

 Смежные вопросы

  • Нет связанных вопросов^_^