Код (Text): mov esi,[mas1] mov edi,[mas2] mov ecx,[len] shr ecx, 3 ; /32 lea esi, [esi+ecx*8] lea edi, [edi+ecx*8] neg ecx @@: movq mm0, [esi+ecx*8] ... movq mm7, [esi+ecx*8+56] .... movq [edi+ecx*8], mm0 .... movq [edi+ecx*8+56], mm7 add ecx, 8 jnz @b emms Использую этот код для копирование блока данных. У меня AMD Athlon 64, 2000 MHz. Подскажите, почему применение инструкции movntq вместо movq при записи данных во 2-й массив ведет к увеличению времени исполнения этой процедуры, хотя здесь http://megaforum.uz/lofiversion/index.php/t15.html говорится об обратном. Использование инструкции prefetchnta [esi] так же не отражается на скорость (даже немного ухудшает показатели). Скорость выполнения измерял через rdtsc.
movntX используются либо 1) для копирования больших блоков данных, размер которых превышает объем кэша L2, либо 2) для записи данных непосредственно в ОЗУ, чтобы не засорять кэши. Если же размер данных небольшой, то возможны две ситуации 1) если ты уже ранее работал со вторым массивом, то соответствующие ему строки уже загружены в кэш и в этом случае movntq даст заметно худшие результаты, чем просто movq 2) если ко второму массиву еще не было обращения, то большой разницы не будет В современных процессорах рулит хардварный префетч, поэтому при последовательном чтении\записи prefetchnta обычно либо ничего не дает, либо даже несколько ухудшает результаты
Да, работал. Попробывал очищать этот массив перед тестированием. Но ничего не дало, использование movntq - дает худший результат. Возможная причина в том, что массив в общем-то небольшой, 400h. Попытаюсь с ним разобраться. Нашел оригинал AMD_block_prefetch_paper.pdf
tar4 Интересно знать каким образом Надеюсь ты понимаешь, что очищать данные в массиве бесполезно, нужно или перезаписать весь кэш L2 левыми данными или выкинуть из кэша все строки, соответствующие твоему массиву (или ручками clflush, или через VirtualAlloc\VirtualFree, тогда винда это сделает за тебя) Для небольших массивов имеет смысл использовать movnt только в случае, когда записанные данные тебе не понадобятся в ближайшем будущем (или же нужно, чтобы они обязательно "сразу" попали в ОЗУ). На всякий случай поясню. При обычной записи процессор сначала читает соответствующие данные из ОЗУ в кэш (read for ownership) и затем уже работает только с кэшем, перезаписывая старые данные новыми. Записанные данные могут сидеть в кэше сколько угодно долго, пока не будут вытеснены другими данными по другим (физическим) адресам. А все movnt пишут данные непосредственно в ОЗУ, минуя кэш. Поэтому если ты после записи собираешься работать с массивом, то лучше использовать обычную запись, а не movnt, т.к. при этом будет двойная работа - сначала данные будут записываться в ОЗУ, а затем считываться из ОЗУ в кэш. Насчет блок-префетча загляни сюда
Увы, я именно так и очищал. Читал я этот топик, половину не понял. Размер кэша L2 - 64 Kb. У меня данные в цикле сначала читаются блоком в 64 байт, потом идет запись этого блока. Нашел статью на Атлону, в которой сказано, что размер блока данных кэша на Атлоне равен 64 байтам. Я так понимаю, что "линейка кэша" и блок данных кэша - это одно и то же?