задержки ММХ

Тема в разделе "WASM.A&O", создана пользователем Drakon Rider, 15 сен 2005.

  1. Drakon Rider

    Drakon Rider New Member

    Публикаций:
    0
    Регистрация:
    15 окт 2002
    Сообщения:
    21
    Адрес:
    Russia
    в функции альфа-блендинга профилеры показывают непонятные задержки на некоторых внутрипроцесорных командах:



    для iP4 2.6 ГГц :



    Intel VTune:

    [​IMG]



    AMD CodeAnalyst:

    [​IMG]



    как я понял клоктики указывают на следующую команду т.е. особо тормозными получаются перемножение pmullw mm7, mm3 и сдвиг на 8 бит psrlq mm7, 08H - я пробовал эти команды непереставить в другие места, но пока особо не помогло... может это какие-то глюки с последним ММХ регистром ? они вроде равноценные все...



    в других местах перемножение и сдвиг занимают заметно меньше времени - похоже что-то в последовательности команд, но как это улучшить ?
     
  2. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine




    Скорее в окружении этого куска кода, сами по себе команды не вызывают задержки в 400 тактов, даже если значение передается между execution unit'ами или через весь конвеер ну максимум ~50 пускай будет, в случае с HT незнаю, но на PIII весь кусок выполняется около 6 тактов



    Или профайлер плужит, или выше этого куска возникает зависимость по данным, или сбросы кеша команд, хз ... вообще странная растактовка для этого кода
     
  3. Drakon Rider

    Drakon Rider New Member

    Публикаций:
    0
    Регистрация:
    15 окт 2002
    Сообщения:
    21
    Адрес:
    Russia
    >сами по себе команды не вызывают задержки в 400 тактов,



    это же не такты, а условные попугаи частости стояния ЦПУ на этих инструкциях...



    >но на PIII весь кусок выполняется около 6 тактов



    а как это получено ? вроде в CodeAnalyst где-то должно показываться сколько тактов будет выполняться инструкция хотя бы на АМД, но я этого не нашел пока :/ ...



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



    вот как получился самый быстрый вариант :
    Код (Text):
    1.  
    2.     movd mm5, eax; // copy alpha_src into mm5
    3.  
    4.      movzx ebx, byte ptr [edi+3]; // ebx: Dst_a
    5.      add ebx, eax; // ebx: Src_a+Dst_a
    6.  
    7.     pxor mm0, mm0;
    8.     pxor mm4, mm4;
    9.  
    10.     movd mm3, [edi];  // ABGR dst in the lower part of mm3
    11.     movd mm2, [esi]; // ABGR src in the lower part of mm2
    12.  
    13.     punpcklbw mm2, mm0; //Unpack mm2 : Src 00aa 00bb 00gg 00rr
    14.     punpcklbw mm3, mm4; // Unpack mm3 : Dst 00aa 00bb 00gg 00rr
    15.    
    16.     movq mm4, mm6; // NUMBER256;
    17.     punpcklwd mm5, mm5;  // Unpack mm2 :0000 0000 00aa 00aa
    18.  
    19.     punpckldq mm5, mm5;  // Unpack mm2 : 00aa 00aa 00aa 00aa
    20.     psubusw mm4, mm5; // mm4: 256-alpha_src
    21.  
    22.     pmullw mm4, mm3; // mm4: (256-alpha_src)*Dst
    23.     pmullw mm5, mm2; // mm5: alpha_src*Src
    24.  
    25.      pmullw mm2, mm3; // Src_a * Dst_a : aaaa xxxx xxxx xxxx
    26.      movd mm1, ebx;// Src_a+Dst_a
    27.      psrlq mm2, 56; // (Src_a * Dst_a / 256) : 0000 0000 0000 00aa - shift and del
    28.  
    29.     paddusw mm4, mm5; // mm4: (256-alpha_src)*Dst + alpha_src*Src
    30.      psubusw mm1, mm2;// mm1: Src_a+Dst_a - (Src_a * Dst_a)/256 : 256 may be here !
    31.  
    32.     psrlw mm4, 8; // ((256-alpha_src)*Dst + alpha_src*Src)/256
    33.      
    34.     packuswb mm4, mm0; // Pack back to bytes : 0000 0000 aabb ggrr
    35.      packuswb mm1, mm0; // limit alpha to 255 ...
    36.  
    37.     pand mm4, mm7; // mm4: 0000 0000 00bb ggrr
    38.      psllq mm1, 24; // mm1: 0000 0000 aa00 0000
    39.  
    40.     por mm4, mm1;
    41.  
    42.     movd [edi], mm4;
    43.  
    44.  




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



    получается четвертопень с длинными конвеерами может очень стремно относиться к спариванию инструкций ? еще непонятно почему медленно выполняется запись в память - на последнем movd [edi], mm4; может стоять под сотню и более попугаев - в несколько раз больше, чем при "быстрой" операции между регистрами...



    еще пробовал то же самое с SSE2 в хмм регистрах делать чтобы по 2 пиксела (2 альфы + 6 цветовых компонент) одновременно обрабатывалось - так получается медленее, чем на показаном обычном ММХ ...
     
  4. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine




    Тогда в них видимо входит время загрузки кода\данных в кеш L1, т.е. включается результат первого прохода, я не представляю как они тогда по этим командам попугаи раскидали



    Я так понимаю это цикл и использует два массива в памяти, думаю сперва стоит протестировать его отдельно, замерив такты от RDTSC по Фогу http://wasm.ru/forum/files/2044615784__wintest.zip , получив таким образом минимальное время выполнения самого кода



    Массивы размещать (под строкой "В А Ш И Д А Н Н Ы Е") выровнеными и с условием, чтобы они влезали в кеш L1



    Под "И Н И Ц И А Л И З А Ц И Я" желательно разместить "mov esi,src\mov edi,dst" и др. не требующие измерений инструкции



    В "Т Е С Т И Р У Е М Ы Е И Н С Т Р У К Ц И И" оставить само тело цикла, лучше чтобы он выполнялся круглое число раз (~1000)



    После запуска wintest.exe покажет окно с результатами 10-ти проходов, типа такого
    Код (Text):
    1. ---------------------------
    2. 000000000000000000515778 - первый проход (подгрузка страниц, линеек)
    3. 000000000000000000025126 - второй
    4. 000000000000000000025120
    5. 000000000000000000025120
    6. 000000000000000000025120
    7. 000000000000000000025120
    8. 000000000000000000035645 - переключение задачи (не брать во внимание)
    9. 000000000000000000025120
    10. 000000000000000000025120
    11. 000000000000000000025120
    12. ------------------------
    Взяв 25120 и разделив на ~1000 имеем 25 тактов время выполнения тела, сперва оптимизировать стоит именно это значение (HT по возможности тоже отключать), а далее уже надо приближать окружение к реальному, менять расположение\размеры массивов и следить как это отобразится с "movd [edi],mm4", т.е. на сколько тактов отклонения от нормы ~25 дает та или иная "композиция" ... попробуй так, лично мне VTune совсем не понравился или я в нем не разобрался