в функции альфа-блендинга профилеры показывают непонятные задержки на некоторых внутрипроцесорных командах: для iP4 2.6 ГГц : Intel VTune: AMD CodeAnalyst: как я понял клоктики указывают на следующую команду т.е. особо тормозными получаются перемножение pmullw mm7, mm3 и сдвиг на 8 бит psrlq mm7, 08H - я пробовал эти команды непереставить в другие места, но пока особо не помогло... может это какие-то глюки с последним ММХ регистром ? они вроде равноценные все... в других местах перемножение и сдвиг занимают заметно меньше времени - похоже что-то в последовательности команд, но как это улучшить ?
Скорее в окружении этого куска кода, сами по себе команды не вызывают задержки в 400 тактов, даже если значение передается между execution unit'ами или через весь конвеер ну максимум ~50 пускай будет, в случае с HT незнаю, но на PIII весь кусок выполняется около 6 тактов Или профайлер плужит, или выше этого куска возникает зависимость по данным, или сбросы кеша команд, хз ... вообще странная растактовка для этого кода
>сами по себе команды не вызывают задержки в 400 тактов, это же не такты, а условные попугаи частости стояния ЦПУ на этих инструкциях... >но на PIII весь кусок выполняется около 6 тактов а как это получено ? вроде в CodeAnalyst где-то должно показываться сколько тактов будет выполняться инструкция хотя бы на АМД, но я этого не нашел пока :/ ... вообщем я сидел вчера и ковырял эту функцию до вечера - под конец получилось, что самое лучшее это не спаривание команд, а наоборот какая-то странная группировка заведомо не спаривающихся, которая позволяет уменьшить относительное время стояния на некоторых инструкциях хотя бы в 2..3 раза... вот как получился самый быстрый вариант : Код (Text): movd mm5, eax; // copy alpha_src into mm5 movzx ebx, byte ptr [edi+3]; // ebx: Dst_a add ebx, eax; // ebx: Src_a+Dst_a pxor mm0, mm0; pxor mm4, mm4; movd mm3, [edi]; // ABGR dst in the lower part of mm3 movd mm2, [esi]; // ABGR src in the lower part of mm2 punpcklbw mm2, mm0; //Unpack mm2 : Src 00aa 00bb 00gg 00rr punpcklbw mm3, mm4; // Unpack mm3 : Dst 00aa 00bb 00gg 00rr movq mm4, mm6; // NUMBER256; punpcklwd mm5, mm5; // Unpack mm2 :0000 0000 00aa 00aa punpckldq mm5, mm5; // Unpack mm2 : 00aa 00aa 00aa 00aa psubusw mm4, mm5; // mm4: 256-alpha_src pmullw mm4, mm3; // mm4: (256-alpha_src)*Dst pmullw mm5, mm2; // mm5: alpha_src*Src pmullw mm2, mm3; // Src_a * Dst_a : aaaa xxxx xxxx xxxx movd mm1, ebx;// Src_a+Dst_a psrlq mm2, 56; // (Src_a * Dst_a / 256) : 0000 0000 0000 00aa - shift and del paddusw mm4, mm5; // mm4: (256-alpha_src)*Dst + alpha_src*Src psubusw mm1, mm2;// mm1: Src_a+Dst_a - (Src_a * Dst_a)/256 : 256 may be here ! psrlw mm4, 8; // ((256-alpha_src)*Dst + alpha_src*Src)/256 packuswb mm4, mm0; // Pack back to bytes : 0000 0000 aabb ggrr packuswb mm1, mm0; // limit alpha to 255 ... pand mm4, mm7; // mm4: 0000 0000 00bb ggrr psllq mm1, 24; // mm1: 0000 0000 aa00 0000 por mm4, mm1; movd [edi], mm4; команды с отступом это отдельный "поток" вычисления альфа-канала, который в принципе мог бы быть спарен с инструкциями основного потока вычисления значений цветов, но при такой попытке возникают непонятные задержки на некотрых операциях см выше ... получается четвертопень с длинными конвеерами может очень стремно относиться к спариванию инструкций ? еще непонятно почему медленно выполняется запись в память - на последнем movd [edi], mm4; может стоять под сотню и более попугаев - в несколько раз больше, чем при "быстрой" операции между регистрами... еще пробовал то же самое с SSE2 в хмм регистрах делать чтобы по 2 пиксела (2 альфы + 6 цветовых компонент) одновременно обрабатывалось - так получается медленее, чем на показаном обычном ММХ ...
Тогда в них видимо входит время загрузки кода\данных в кеш L1, т.е. включается результат первого прохода, я не представляю как они тогда по этим командам попугаи раскидали Я так понимаю это цикл и использует два массива в памяти, думаю сперва стоит протестировать его отдельно, замерив такты от RDTSC по Фогу http://wasm.ru/forum/files/2044615784__wintest.zip , получив таким образом минимальное время выполнения самого кода Массивы размещать (под строкой "В А Ш И Д А Н Н Ы Е") выровнеными и с условием, чтобы они влезали в кеш L1 Под "И Н И Ц И А Л И З А Ц И Я" желательно разместить "mov esi,src\mov edi,dst" и др. не требующие измерений инструкции В "Т Е С Т И Р У Е М Ы Е И Н С Т Р У К Ц И И" оставить само тело цикла, лучше чтобы он выполнялся круглое число раз (~1000) После запуска wintest.exe покажет окно с результатами 10-ти проходов, типа такого Код (Text): --------------------------- 000000000000000000515778 - первый проход (подгрузка страниц, линеек) 000000000000000000025126 - второй 000000000000000000025120 000000000000000000025120 000000000000000000025120 000000000000000000025120 000000000000000000035645 - переключение задачи (не брать во внимание) 000000000000000000025120 000000000000000000025120 000000000000000000025120 ------------------------ Взяв 25120 и разделив на ~1000 имеем 25 тактов время выполнения тела, сперва оптимизировать стоит именно это значение (HT по возможности тоже отключать), а далее уже надо приближать окружение к реальному, менять расположение\размеры массивов и следить как это отобразится с "movd [edi],mm4", т.е. на сколько тактов отклонения от нормы ~25 дает та или иная "композиция" ... попробуй так, лично мне VTune совсем не понравился или я в нем не разобрался