Копирование из памяти в память (MMX)

Тема в разделе "WASM.BEGINNERS", создана пользователем tar4, 23 май 2007.

  1. tar4

    tar4 New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2006
    Сообщения:
    43
    Код (Text):
    1.     mov     esi,[mas1]
    2.     mov     edi,[mas2]
    3.     mov         ecx,[len]      
    4.     shr          ecx, 3         ; /32
    5.     lea esi,    [esi+ecx*8]    
    6.     lea edi,    [edi+ecx*8]  
    7.     neg ecx                
    8. @@:
    9.     movq mm0, [esi+ecx*8]
    10.         ...
    11.     movq mm7, [esi+ecx*8+56]
    12.         ....
    13.     movq      [edi+ecx*8],    mm0
    14.         ....
    15.     movq    [edi+ecx*8+56], mm7
    16.     add ecx, 8
    17.     jnz @b
    18.     emms
    Использую этот код для копирование блока данных. У меня AMD Athlon 64, 2000 MHz. Подскажите, почему применение инструкции movntq вместо movq при записи данных во 2-й массив ведет к увеличению времени исполнения этой процедуры, хотя здесь http://megaforum.uz/lofiversion/index.php/t15.html
    говорится об обратном.
    Использование инструкции prefetchnta [esi] так же
    не отражается на скорость (даже немного ухудшает показатели). Скорость выполнения измерял через rdtsc.
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    movntX используются либо 1) для копирования больших блоков данных, размер которых превышает объем кэша L2, либо 2) для записи данных непосредственно в ОЗУ, чтобы не засорять кэши. Если же размер данных небольшой, то возможны две ситуации
    1) если ты уже ранее работал со вторым массивом, то соответствующие ему строки уже загружены в кэш и в этом случае movntq даст заметно худшие результаты, чем просто movq
    2) если ко второму массиву еще не было обращения, то большой разницы не будет

    В современных процессорах рулит хардварный префетч, поэтому при последовательном чтении\записи prefetchnta обычно либо ничего не дает, либо даже несколько ухудшает результаты
     
  3. tar4

    tar4 New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2006
    Сообщения:
    43
    Да, работал. Попробывал очищать этот массив перед тестированием. Но ничего не дало, использование movntq - дает худший результат.
    Возможная причина в том, что массив в общем-то небольшой, 400h.
    Попытаюсь с ним разобраться. Нашел оригинал
    AMD_block_prefetch_paper.pdf
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    tar4
    Интересно знать каким образом ;) Надеюсь ты понимаешь, что очищать данные в массиве бесполезно, нужно или перезаписать весь кэш L2 левыми данными или выкинуть из кэша все строки, соответствующие твоему массиву (или ручками clflush, или через VirtualAlloc\VirtualFree, тогда винда это сделает за тебя)

    Для небольших массивов имеет смысл использовать movnt только в случае, когда записанные данные тебе не понадобятся в ближайшем будущем (или же нужно, чтобы они обязательно "сразу" попали в ОЗУ). На всякий случай поясню. При обычной записи процессор сначала читает соответствующие данные из ОЗУ в кэш (read for ownership) и затем уже работает только с кэшем, перезаписывая старые данные новыми. Записанные данные могут сидеть в кэше сколько угодно долго, пока не будут вытеснены другими данными по другим (физическим) адресам. А все movnt пишут данные непосредственно в ОЗУ, минуя кэш. Поэтому если ты после записи собираешься работать с массивом, то лучше использовать обычную запись, а не movnt, т.к. при этом будет двойная работа - сначала данные будут записываться в ОЗУ, а затем считываться из ОЗУ в кэш.

    Насчет блок-префетча загляни сюда
     
  5. tar4

    tar4 New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2006
    Сообщения:
    43
    Увы, я именно так и очищал.
    Читал я этот топик, половину не понял.
    Размер кэша L2 - 64 Kb. У меня данные в цикле сначала читаются блоком в 64 байт, потом идет запись этого блока.
    Нашел статью на Атлону, в которой сказано, что размер блока данных кэша на Атлоне равен 64 байтам.
    Я так понимаю, что "линейка кэша" и блок данных кэша - это одно и то же?