|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Окт 30, 2004 10:30:42 · Поправил: leo "Уговорить" P4-1800 15.2.4 выполнять ADC с перекрытием никак не удается. При развороте большую часть MOV удается распараллелить с ADC, но сами ADC все равно выполняются последовательно, поэтому общую задержку менее ~1050-1100 тиков получить не удается (т.е. ~8 тактов на сложение = latency ADC). Перепробовал все варианты расположения mov и, ради экперимента, вообще закоментировал все mov, оставив одни ADC - нет не желают они перекрываться и все тут. Видимо Intel-ы чего-то напутали: или в мануале опечатка или блок динамического исполнения "недоделанный". В мануале для ADC throughput = 3, а на деле получается ~8 = latency. (По определению: "Throughput - the number of clock cycles required to wait before the issue ports are free to accept the same instruction again"). Вывод простой: ADC на P4 - это "тормозной отстой" :) |
|
|
Дата: Ноя 2, 2004 16:44:16 leo > "Уговорить" P4-1800 15.2.4 выполнять ADC с перекрытием никак не удается." Увы, на мои уговоры процессор также не поддался. Похоже, что тема себя исчерпала и пора мне подводить итоги. Через пару дней сделаю :) |
|
|
Дата: Ноя 3, 2004 08:59:52 leo > Видимо Intel-ы чего-то напутали: или в мануале опечатка или блок динамического исполнения "недоделанный". В мануале для ADC throughput = 3, а на деле получается ~8 = latency. Да зачем intel'у путать в доках, причем от версии к версии.. Есть такое понятие, как заваисимость по данным. Пока данные для операции не готовы, выполняться она не будет. ADC ждёт результатов выполнения предыдущего ADC. Именно поэтому в данном случае и получается, что throughput не 3, а "как бы" 8. |
|
|
Дата: Ноя 3, 2004 14:00:52 · Поправил: leo S_T_A_S_ Насчет зависимости я конечно понимаю и не зря подчеркнул цитату "to accept the same instruction again". Вопрос в том, как понимать "the same" - как "точно такую же" или "похожую, аналогичную". Последовательные инструкции ADC всегда являются зависимыми и если вторая вынуждена всегда ждать первую, то интелам не стоило бы морочить людям голову и указывть throughput = 3 вместо 8, если под "the same" в данном случае имеется ввиду такая же ADC. Если же под throughput понимается просто освобождение порта для принятия другой инструкции - тогда понятно. И потом, у меня теплилась надежда на то, что все-таки флаг CF играет особую роль, т.к. используется в ADC\SBB и поэтому устаналивается не только в EFLAGS, откуда его потом долго извлекать (сутя по latency ADC,SBB,SETC), а еще и в некий дополнительный бит или темп-регистр. И тогда, если бы P4 был бы "поумнее", вторая ADC могла бы работать быстрее, беря на лету это значение CF не связываясь с EFLAGS. Но к сожалению, это оказалось бесплодными фантазиями. PS: Посмотрел, что пишет Агнер Фог (pentopt.pdf), так у него для ADC на P4 приводится throughput = latency = 6 для r,r и 8 для r,m. Все ясно и понятно. |
|
|
Дата: Ноя 4, 2004 00:00:34 leo Возможно если между первой ADC и второй вставить инитрукцию, которая "разобьет" зависимость между ними, то тогда и только тогда будет throughput = 3? |
|
|
Дата: Ноя 4, 2004 09:13:44 leo > Насчет зависимости я конечно понимаю и не зря подчеркнул цитату "to accept the same instruction again". Вопрос в том, как понимать "the same" - как "точно такую же" или "похожую, аналогичную". „Для неведомого все имена, что одно.
Видеть в чудесном чудесное - вот ключ ко всем тайнам мира.“
> Посмотрел, что пишет Агнер Фог (pentopt.pdf), так у него для ADC на P4 приводится throughput = latency = 6 для r,r и 8 для r,m. Все ясно и понятно. Как-то один очень уважаемый мною человек сказал мне, что athlon способен выполнить 9 nop за такт. Только по прошествии большого количества времени я (надеюсь) понял, что он хотел мне сказать. В 2х словах смысл такой: Существует как непроверенная информация, так и официальная документация! |
|
|
Дата: Ноя 4, 2004 09:36:29 · Поправил: leo S_T_A_S_ Все-таки я не понимаю, что ты хочешь сказать. Я вроде бы свою мысль уже пояснил: если 3 - это время освобождения порта для приема (не обязательно начала исполнения) следующей инструкции, то ясно. НО если следующая ADC всегда вынуждена ждать завершения предыдущей ADC, то реальный темп выполнения последовательных ADC будет >= 8 тактов. Правильно ? Что касается уважаемого Агнера, то он приводит другую, более понятную величину reciprocal throughput: This value indicates the number of clock cycles from the execution of an instruction begins to a subsequent independent instruction can begin to execute in the same execution subunit. Как видим, эта величина больше соответствует тому, что мы хотим знать об ADC, чем величина throughput приводимая Intel. |
|
|
Дата: Ноя 4, 2004 10:29:01 · Поправил: semen Хмм.. И все-же разбивание зависимости влияет: RDTSCTimer timer; timer.StartCount(); __asm { mov ecx, 100000 mov ebx, 1 xor eax, eax .align 16 loop_: adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx adc eax, ebx dec ecx jnz loop_ } __int64 time = timer.GetTime(); printf("processor ticks without break: %I64i\n", time); timer.StartCount(); __asm { mov ecx, 100000 mov ebx, 1 xor eax, eax .align 16 loop2_: mov edx, 0xffffffff adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx shl edx, 1 adc eax, ebx dec ecx jnz loop2_ } time = timer.GetTime(); printf("processor ticks with break: %I64i\n", time); Что выдает на моем P4Mobile-1700 F15 M2 S4: processor ticks without break: 11953340 processor ticks with break: 9814656 Т.е. с разбиением 6 тиков на adc и сдвиг на P4-2800 F15 M2 S9: processor ticks without break: 11448676 processor ticks with break: 6386308 Т.е. с разбиением 4 тика на adc и сдвиг на Dual P2-300 F6 M3 S3: processor ticks without break: 3921358 processor ticks with break: 4022432 - 2.5 тика |
|
|
Дата: Ноя 4, 2004 11:07:41 · Поправил: leo semen Да, результат интересный в познавательном плане. Вот только перенос при такой разбивке теряется и к задаче сложения это видимо никак не "прицепишь". PS: С P2,P3 (Family 6) все понятно, там и ADC 2-3 такта. |
|
|
Дата: Ноя 4, 2004 11:59:43 leo > если следующая ADC всегда вынуждена ждать завершения предыдущей ADC, то реальный темп выполнения последовательных ADC будет >= 8 тактов. Ну почему же всегда? CF можно учитывать другим способом, и добавить инструкции убирающие зависимость по данным (см. пример semenа) > эта величина больше соответствует тому, что мы хотим знать об ADC, чем величина throughput приводимая Intel. Вот здесь ключевое слово "хотим". Такая уж психология у людей - из 2х вариантов ответа выбирается не тот, который правильный, а тот что по душе. Захотим - у нас и the same будет значить "похожую, аналогичную" :) > Вот только перенос при такой разбивке теряется и к задаче сложения это видимо никак не "прицепишь". А это и не удивительно, т.к. задача до сих пор толком не поставлена - не понятно в каком формате хранятся числа. Если же знать формат, знать о (не)возможности складывать 2 пары чисел параллельно - тогда можно перейти от слов "видимо" к "очевидно".. ЗЫ: про "любой формат" мне можно не напоминать, я пытался делать предположения, а они оказались частным случаем. А как можно сочинять свой формат не зная толком как он потом будет использоваться, не пойму :( |
|
|
Дата: Ноя 4, 2004 13:55:37 · Поправил: leo S_T_A_S_ Ты все о своем. Почему "обычные"-то числа нельзя складывать. Есть же int16, int32, int64, так почему бы и int512 не использовать. Gray прав - вроде бы все уже выжали из "обычного" сложения. Если интересно, то можно и другие форматы рассмотреть или параллельное сложение двух пар чисел. Хотя до кучи вот еще вариантик - с использованием циклического сдвига RCL, который работает несколько быстрее SETC: shr ecx,2
xor edx,edx
xor ebp,ebp
align 16
@@loop:
mov eax,[esi]
mov edi,[ebx]
or edx,ebp
add edi,eax
rcl ebp,1
and edx,1
add edi,edx
mov [ebx],edi
rcl edx,1
.............
;разворот цикла на 4: +3 повтора со смещением 4, 8 и 12
.............
lea esi,[esi+16] ;add esi,16 - без разницы
lea ebx,[ebx+16]
sub ecx,1 ;dec ecx - хуже
jnz @@loop}Также возможна "статистическая" модификация с заменой rcl edx,1 на jc:mov eax,[esi] mov edi,[ebx] add edi,eax rcl ebp,1 and edx,1 add edi,edx mov [ebx],edi jc @@carry1 mov edx,ebp @@carry1:Результаты на P4-1800 (15.2.7): Gray.............1428 leo_rcl..........1008 leo_rcl_jc.......816,900,828,828... - разные цифры для проходов 2,3 и 4-8 для данных Data1 Gray ...............................видимо из-за наличия переходов по jc |
|
|
Дата: Ноя 4, 2004 13:57:47 · Поправил: semen leo Да, результат интересный в познавательном плане. Вот только перенос при такой разбивке теряется и к задаче сложения это видимо никак не "прицепишь". PS: С P2,P3 (Family 6) все понятно, там и ADC 2-3 такта. Ну я о познавательном плане и заботился... к тому что интел не соврал про throughput = 3... и если в этой задаче не получится использовать быстрый adc - в другой получится... |
|
|
Дата: Ноя 4, 2004 14:10:10 semen Ясно, спасибо |
|
|
Дата: Ноя 7, 2004 10:55:05 · Поправил: leo Учел замечания semen и S_T_A_S_ по возможности перекрытия ADC за счет добавления инструкций, учитывающих перенос и устраняющих зависимость ADC. На P4 15.2.7 получаются превосходные результаты при развороте цикла на 4 сложения: macro leo_ADC_fast4{
shr ecx,2
clc
align 16
.loop:
mov eax,[esi]
mov edi,[ebx]
mov ebp,eax
adc eax,edi ;ADC[0] <--- EAX
;устраняем зависимость
add ebp,edi ;"основной" перенос
inc ebp ;контроль "редкого" случая x[i]+y[i] = $FFFFFFFF
jz .carry1
.ret1:
mov edx,[esi+4]
mov edi,[ebx+4]
mov ebp,edx
adc edx,edi ;ADC[4] <--- EDX
;устраняем зависимость
add ebp,edi
inc ebp
jz .carry2
.ret2:
mov [ebx],eax ;---> MOV[0] EAX
mov eax,[esi+8]
mov edi,[ebx+8]
mov ebp,eax
adc eax,edi ;ADC[8] <--- EAX
;устраняем зависимость
add ebp,edi
inc ebp
jz .carry3
.ret3:
mov [ebx+4],edx ;---> MOV[4] EDX
mov edx,[esi+12]
mov edi,[ebx+12]
adc edx,edi ;ADC[12] <--- EDX
;здесь остается ждать результата
mov [ebx+8],eax ;---> MOV[8] EAX
mov [ebx+12],edx ;---> MOV[12] EDX
lea esi,[esi+16]
lea ebx,[ebx+16]
dec ecx
jnz .loop
jmp .end
.carry1:
;--- коррекция CF ---
;здесь ebp = x+y+1 = 0 => либо eax = 0 (был перенос и будет),
; либо eax = -1 = $FFFFFFFF (не было переноса и не будет)
cmp eax,-1 ;CF установится если eax = 0, т.е. eax ниже $FFFFFFFF
jmp .ret1
.carry2:
cmp edx,-1
jmp .ret2
.carry3:
cmp eax,-1
jmp .ret3
.end:
};==========================================Можно учет переноса по JZ вставить в тело цикла, но при этом результаты получаются несколько хужеadd ebp,edi inc ebp ;db $3E ;префикс выполнения прыжка, при нескольких проходах ничего не дает jnz .ret1 cmp eax,-1 .ret1: .......Вот результаты на P4-1800 (15.2.7) Gray...............1428 Gray_SSE2...........940 leo_JZ..............832 leo_ADC_fast4......732,776,728,676,676... ;рез-ты проходов 2,3.. по Data1 Gray leo_ADC_fast4jnz...756,772,772,692,692... ;- " -Кстати на P4 15.2.4 этот же код дает заметно худшие результаты, а предварительный разворот на 8 сложений тоже получается чуть хуже => остаются какие-то зависимости от расположения инструкций, длины тела цикла и т.п. |
|
|
Дата: Ноя 9, 2004 12:05:03 leo, ты меня поражаешь! Я уж думал, что все из процессора уже выжали, а ты своим leo_ADC_fast4 показал, что сие вовсе не так. leo >"На P4 15.2.7 получаются превосходные результаты при развороте цикла на 4 сложения..." На P4 15.2.9 результаты столь же превосходны, завтра протестирую на других процессорах. P.S. Воистину nop так же неисчерпаем как и pop :) |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.184 |