Не знаю, визуально вроде разница только bswap vs shr, второе должно быть быстрее - на деле наоборот. Тут мысль одна появилась - не по полбайта обрабатывать, а побайтно, но к сожалению удалось только для одного байта так сделать - в регистре увы, только 32 разряда. Было бы 33 - можно было бы 2 раза такое провернуть. Для первого и последнего полубайта: Код (Text): mov ecx,87654321h ;------------------------------------------------------- mov eax,ecx mov ebx,2040810h and eax,11110000000000000000000000001111b mul ebx and edx,00000001000000010000000100000001b and eax,00010000000100000001000000010000b add edx,30303030h shr eax,4 bswap edx add eax,30303030h mov [edi],edx bswap eax mov [edi+28],eax С таким фокусом удалось из 4-х десятков выскочить - 36 тиков. Остальные тетрады бит по прежнему сделаны.
cresta > "Тут мысль одна появилась - не по полбайта обрабатывать, а побайтно" Гениально ! И умножение на 08040201h позволяет это сделать: Код (Text): ;в edx - байт imul edx,08040201h mov ecx,edx shr edx,3 ;биты 4..1 в нужном порядке shr ecx,7 ;биты 8..5 в нужном порядке ... + специи по вкусу ;) PS: и все-таки твой Атлон - капризный Может он любит в перестановки играть и замены or на add )
А че мы за рекордами по тикам гоняемся Может симпатичный цикл сделать на 4 байта: Код (Text): ;push edi, push ebx mov edi,bin_str mov eax,87654321h ;================= mov ecx,24 align 16 ;на 4 прохода может и align то не нужен @@: mov edx,eax and edx,0FFh imul edx,08040201h shr eax,8 and edx,88888888h mov ebx,edx shr edx,3 shr ebx,7 or edx,30303030h mov [edi+ecx+4],edx or ebx,30303030h mov [edi+ecx],ebx sub ecx,8 jge @B ;pop ebx, pop edi ;mov byte [edi+32],0 ;замыкающий нолик не забыть ! На P4 получается 60-64 тика (для сравнения исходный вариант bogrus - 116 тиков, первый вариант cresta - 76 тиков). Кстати, на P4 опять cpuid искажает тики при записи в память, поэтому приведенные результаты - это с CLD. Надо бы поэкспериментировать да с kaspersky подискутировать на эту тему, а то он опять пропал
leo Подкалываешь Похоже ты не понял. Я говорю не о стоящих подряд битах. Умножение на 204081h "размазывает" младший полубайт равномерно по всему дворду с периодичностью 8 бит, осталось только and и add/or. Код (Text): mov eax,87654321h ;[b]1000[/b]0111011001010100001100100001 shr eax,28 ;0000000000000000000000000000[b]1000[/b] imul eax,204081h ;0000000[b]1[/b]0000001[b]0[/b]0000010[b]0[/b]0000100[b]0[/b] and eax,01010101h ;0000000[b]1[/b]0000000[b]0[/b]0000000[b]0[/b]0000000[b]0[/b] add eax,30303030h ;31303030h А эта штука (08040201h) выдаёт биты в беспорядке, никакой периодичности ни для старших, ни для младших тут не видно. Просто напрасно выполненный код. Код (Text): mov edx,87654321h ;10000111 01100101 01000011 00100001 imul edx,08040201h ;01100110 01101111 10000101 00100001 mov ecx,edx ;01100110 01101111 10000101 00100001 shr edx,3 ;00001100 11001101 11110000 10100100 shr ecx,7 ;00000000 11001100 11011111 00001010 Заменой множителя с 204081h на 2040810h я "размазываю" не полубайт, а байт, на пару регистров edx/eax: в edx старшая тетрада, в eax младшая. Биты, которые будут преобразованы, стоят не подряд, а на позициях 31-28 и 3-0. Код (Text): mov ecx,87654321h ;10000111 01100101 01000011 00100001 mov eax,ecx ;10000111 01100101 01000011 00100001 mov ebx,2040810h ;для mul вместо imul and eax,0F000000F ;[b]1000[/b]0000 00000000 00000000 0000[b]0001[/b] mul ebx ;в edx - биты 31-28, в eax - биты 3-0 ;в обоих регистрах с периодичностью 8 бит. and edx,01010101h ;0000000[b]1[/b] 0000000[b]0[/b] 0000000[b]0[/b] 0000000[b]0[/b] and eax,10101010h ;000[b]0[/b]0000 000[b]0[/b]0000 000[b]0[/b]0000 000[b]1[/b]0000 shr eax,4 ;0000000[b]0[/b] 0000000[b]0[/b] 0000000[b]0[/b] 0000000[b]1[/b] add edx,30303030h ;31303030h add eax,30303030h ;30303031h Но это получается только для крайних тетрад исходного дворда (31-28 и 3-0). Если расстояние между ними меньше, то младшие биты после умножения частично оказываются в edx (в исходном дворде допустим они начинаются не 3-0, а 7-4). Можно конечно после умножения двинуть вправо eax через флаг переноса, чтобы вернуть старший бит из edx в eax. Это должно позволить обработать таким манером два раза. Т.е. (31-28 и 7-4) и (27-24 и 3-0). P.S. замена or на add - совершенно идентично (по скорости) P.P.S. Что-то попытался биты цветом выделить - ерунда получилась Пришлось на bold поменять.
Попытался в целях упаковки воспользоваться коммандой pmovskb (MMX,PIII) и был разочарован - на AMD AthlonXP Throughbred каждая такая коммада награждается штрафом в 10-13 тиков (по сведениям CodeAnalyst - stlf opsize), и производительность в результате у алгоритма получается неважная.
cresta Возможно я тебя не понял, а ты меня А умножение байта на 08040201h раскидывает биты по разным тетрадам с инверсией порядка. Перед умножением в edx ес-но должен быть только байт (8 младших разрядов) и никакого перемешивания тут происходить не может. Пример: умножаем столбиком 08040201 на FF: Код (Text): 8 4 2 1 1 0000[b]1[/b]000000001000000001000000001 <-младший бит 2 0000100000000[b]1[/b]000000001000000001 3 0000100000000100000000[b]1[/b]000000001 4 0000100000000100000000100000000[b]1[/b] 5 0000[b]1[/b]000000001000000001000000001 6 0000100000000[b]1[/b]000000001000000001 7 0000100000000100000000[b]1[/b]000000001 8 0000100000000100000000100000000[b]1[/b] result [b]1[/b]111[b]1[/b]011[b]1[/b]111[b]1[/b]101[b]1[/b]111[b]1[/b]110[b]1[/b]111[b]1[/b]111 and [b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000[b]1[/b]000 ;<- младший биты [b]5[/b] [b]1[/b] [b]6[/b] [b]2[/b] [b]7[/b] [b]3[/b] [b]8[/b] [b]4[/b] потом SHR-ми и OR-ми разделяем биты\байты 1-2-3-4 и 5-6-7-8 Ес-но если берем не FF, а другое значение, то там где бит = 0, соответсвующее слагаемое отсутствует и соответсвующий выходной бит = 0. PS: Да суть то умножения одна и таже, что у тебя, что у меня. Просто 1) нарастание сдвига от младших к старшим как в 08040201 позволяет получить инверсию, 2) расстояние между битами множителя позволяет уместить 8 бит множимого без перемешивания, и запаса старших битов как раз хватает чтобы получить в старшей тетраде 5-й бит; 3) в твоем случае между битами множителя x81 не достаточно расстояния чтобы уложить нужные 8 бит, поэтому ты придумал другой подход - прихватить edx
cresta, ты как убедился что мой вариант работает правильно ? Результаты на PIII: Код (Text): 94 исходный вариант bogrus 44 первый вариант cresta 50,40 вариант leo (цикл по 4 байтам) 42,34 тоже с некоторыми перестановками Две цифры - вляние выравнивания (с выравниваем хуже, частично м.б. потому что число проходов мало и эффект мал, а нопы - тики съедают). Суть перестановки, улучшающей результат на PIII(на P4 это ничего не дает): парочку mov edx,eax + and edx,0FFh переносим вслед за mov [edi..],edx и дополнительно добавляем ее перед циклом для первого прохода
alpet > Я тоже заметил, что многие vector path команды выполняются "быстрее" чем заявлено в документации за счёт спаривания не некоторых стадиях с direct path командами. В CodeAnalyst это хорошо видно, да и замеры деревенскими способами это подтверждают leo > На athlon эта команда выполняется за один такт
S_T_A_S_ Вот и я думаю, что за 1 такт - быстрее некуда Поэтому +4 тика при замене 8 bswap на 8 shr, можно объяснить только "потусторонними" эффектами (декодер, порты, спаривание и т.п.) Чего-то мне кажется вы с alpet противоположные вещи говорите Суть то у него правильная, но вот противопоставление "группы однотипных операций" и "среди более быстрых" - вызывает сомнение (если эти быстрые не завясят от медленной).
leo С разворотом бит разобрался. Имхо, на таких величинах уже трудно определить, что быстрее. Разница - единицы. align туда - align сюда и все переворачивается. На атлоне с умножением на 02040810h - 36 с умножением на 08040201h - 33 с табличкой вариант alpet - 32 Разницы в десятки тиков уже нет.
leo Суть в том, что vector path команды тоже иногда паралелятся по не указанным в документации причинам
Мне в последнее время сдается также что и CodeAnalyst иногда привирает при анализе эмулируемого кода. Иногда он мне подставляет пенальти bank conflict в коммандах даже близко не работающих с памятью. Блин разобраться бы в API его библиотек (особенно *sim32.dll) и переписать эту программу по нормальному... А вообще меня эта программа потихоньку обучает, до знакомства с ней я плохо представлял как работает суперскалярная архитектура, теперь еще надо с VTune познакомиться.
В VTune анализа пайпа нет А что до корректности результатов эмуляции - я как-то тоже усомнился, проверил rdtsc - всё оказалось верно.