Доброе время суток. Необходима функция, которая преобразует байт в строку(2 hex символа), к примеру 0xAA -> "AA\0". Я сделал так: Код (Text): section '.text' code readable executable public ByteToChar as '@ByteToChar@4' ByteToChar: mov esi,hexTable mov edi,strBuf xor ebx,ebx mov bl,cl and bl,0xF0 shr bl,4 mov al,[esi+ebx] mov bl,cl and bl,0x0F mov ah,[esi+ebx] mov [edi],ax mov eax,strBuf ret section '.data' data readable writeable align 16 hexTable db "0123456789ABCDEF",0 strBuf dd 0 В результате получил ~17500 тактов (PentiumD930) на 1024 байт, ~17 тактов на байт. Как можно улучшить данный код?
на разных процах разный результат будет, можно только ориентироваться на "больше-меньше" Твой вариант дает 8 тиков (тестилкой от bogrus) такой вариант дает 4 тика (в масм-синтаксисе): Код (Text): mov eax,offset strBuf movzx edx,cl and ecx,0Fh shr edx,4 movzx ecx,byte ptr[hexTable+ecx] movzx edx,byte ptr[hexTable+edx] mov [eax+1],cl mov [eax],dl регистров меньше используется - не надо сохранять esi edi ebx. P.S. а если расположить инструкции в несколько ином порядке, то получается вообще 3 тика (за счет экономии на ожидании результата) Код (Text): movzx edx,cl and ecx,0Fh shr edx,4 mov eax,offset strBuf movzx ecx,byte ptr[hexTable+ecx] movzx edx,byte ptr[hexTable+edx] mov [eax+1],cl mov [eax],dl
Превосходно! Большое спасибо! Решил тоже прогнать тестом bogrus'a, и получил интересные результаты: 1) AMD Athlon (на работе машина) Мой вариант: 8 тактов cresta (1й вариант): 4 такта cresta (2й вариант): 3 такта(!), замечательно 2) Pentium MMX Мой вариант: 18-20 (чередуется) cresta (1й вариант): 33-35 тактов (чередуется) cresta (2й вариант): 32-34 такта (чередуется) 3) PentiumD (всеми любимый netbusrt)), перед тестом вызываю SetProcessAffinityMask) Мой вариант: 540 тактов (это как так???) cresta (1й вариант): 945 тактов cresta (2й вариант): 975 тактов Если тестировать из C-проги то получается так: Мой вариант: ~17560 тактов на 1024 байт cresta (1й вариант): ~16800 тактов на 1024 байт cresta (2й вариант): ~17200 тактов на 1024 байт Теперь вопрос: Почему так? Почему на netburst'e такие результаты странные, и почему тест bogrus'a выдает так много тактов, когда прога на C++ вызывает функцию 1024 раза, и получается не >17000 тактов? Что-то я ничего не понимаю... А вот на такую последовательность pxor mm3,mm6 paddb mm3,mm6 psubd mm6,mm3 тест выдает: 2805 0 15 0 0 15 0 15 0 0 И вообще результаты какие-то странные, разброс сильный, и результат с нулями чередуется.... А если переместить переменную и таблицу в секцию '.data' то результаты вообще такие: 75 остальное - нули.... Интересные фокусы....
у меня Athlon XP 2400, под него я и попытался сделать быстрее (твой тест тоже подтверждает это). Что для атлона хорошо - для пня смерть Чтобы сделать быстро на пне, или какой-то универсальный (компромиссный) вариант, нужно несколько разных процессоров. У меня их нет Чтобы добиться скорости везде, надо в первую очередь оптимизировать алгоритм, а не набор инструкций, которыми он реализован. А функция у тебя простейшая, особо с алгоритмами не развернешься. Если эта процедура настолько критична, делай два разных кода под разные процы, и вызывай тот или иной в зависимости от процессора. И когда вызываешь из Си-проги процедуру, как ты учитываешь время на организацию самого вызова? Одна только пара call/ret будет больше времени занимать, чем собственно сам код перевода числа в строку. Может не надо её отдельной функцией? Моя асмовая тестилка затерялась в дебрях винта, вот приаттачиваю сишную, посмотри, как устроена. Всё инлайн, никаких вызовов функций. Эта тестилка показывает 5 тиков. Почему у тебя сишный показывает 16 - не знаю, смотри свой код, сравнивай с аттачем.
Спасибо, сейчас потестирую.... Сишная показывает ~240-255 тактов в Debug'e и 30-45 в Release'e... Что с результатами такое? Почему они везде разные? (я не про Debug и Release, а вообще). В тесте bogrus'a, к примеру бывает, что блок выполняется за 0 тактов.... Что это вообще происходит? )
трудно сказать, почему у тебя нули. Тот mmx-код, который ты привел, показывает устойчиво 7 тиков, как в асм-тестилке bogrus'a, так и в моей сишной (из аттача). Может, какие-нибудь некорректности в коде приводят к каким-то исключительным ситуациям? Я с mmx никогда не работал, не знаю...
xdev86_ Это ваши совместные фокусы с Intel Corp. Фокус №1. В NetBurst запись в секцию кода в одном килобайте с исполняемым кодом приводит к сбросу Т-кэша и ес-но к большим штрафам. По видимому этим объясняются твои 500-900 тиков на Pentium D - кури мануалы и без особой необходимости ничего не пиши в секцию кода Фокус №2 - недокументированный, но подтверждаемый на практике. RDTSC выдает результаты с дискретом: 4 тика на первых моделях P4, 8 тиков на P4E и 15 тиков в Pentium D (да еще и скачет на +-15 если включены оба ядра). Поскольку у тебя задержка меньше 15 и второе ядро ты не отключал, то и получаешь болтанку между 0 и 15
OK, спасибо, теперь понятно. Я когда перенес в секцию данных оно стало нули показывать Теперь ясно почему. Я теперь замеряю время 100 вызовов, и просто получает среднее арифметическое. Только не понимаю, зачем нужно было так rdtsc уродовать? ЗЫ: Все-таки какие-то кривые эти p4. Мне P6 всегда больше нравилась...
Интересно, какую скорость покажет такой вариант: add al,90h daa adc al,40h daa mov strBuf+1,al add al,90h daa adc al,40h daa mov strBuf,al
MikDay Черепашью На атлонах одна DAA кушает 7-8 тактов, а на P4, если верить Фогу, от 29 до 100 тиков в завис-ти от модели
xdev86_ не знаю как ты там меряешь, на х2 твой код показал 15, варианты cresta 4 и 3 соотв. MikDay - 24 (все в тактах ес-но)
Я писал выше, как и чем я меряю, и почему у меня такие результаты. И что такое есть x2, Athlon X2? Что-то много, 15 тактов... Так же интересно посмотреть на твой метод тестирования.
Приведенный мной алгоритм был когда-то в BIOS старых компьютеров. Вероятно там упор был не на скорость, а на минимальный код. Выглядел он приблизительно так: hex proc push ax shr al,4 call hex2 pop ax and al,0Fh hex2 proc add al,90h daa adc al,40h daa mov ah,0Eh int 10h ret hex2 endp hex endp Я, кстати, сделал ошибки в своем примере - не выделил старшую тетраду.
профилировщик (с) Maverick я не смотрел как именно bogrus сделал профилировщик, но не может быть разница на порядок, согласись. Да, х2 это атлон х2.