Спекулятивное исполнение команд деления

Тема в разделе "WASM.A&O", создана пользователем v_mirgorodsky, 27 ноя 2006.

  1. v_mirgorodsky

    v_mirgorodsky New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    53
    Пусть есть массив из 64 12-разрядных знаковых чисел. Весь массив необходимо разделить на некоторые фиксированные значения. Делитель первого коеффициента отличается от делителя всех последующих. Кроме того, для первого коеффициента важно знать остаток от деления. Пока все просто, а вот дальше начинаются странности.

    MMX часть макроса требует ~217 тактов на выполнение, хотя по прилагаемой псевдо-научной симуляции должно требоваться не более 112. Куда процессор девает еще 100 тактов - полная загадка :dntknw:

    Возникает впечатление, что idiv ecx блокирует конвеер на 25-30 тактов, поскольку при добавлении ее в тело макроса время его выполнения увеличивается до ~240 тактов. Да, если idiv ecx заменить на несколько imul ecx, то общее время выполнения макроса снова становится равным 217 тактов, т.е. латентность других команд все же прячется ;)

    Да, забыл сказать, что все это происходит на P4 Prescott, 3.0GHz.

    P.S. Тему следовало назвать "Латентность исполнения команд деления". Если возможно - прошу изменить название.

    Код (Text):
    1. quant           macro       coef:req,xquant:req,quant:req
    2.                 movzx       ecx,word ptr xquant                             ; ecx = xquant
    3.                 mov         ebx,ecx                                         ; ebx = xquant
    4.                 shr         ebx,1                                           ; ebx = xquant / 2
    5.                 movsx       eax,word ptr coef[0]                            ; eax = coef[0]
    6.                 cdq                                                         ; edx = sign(coef[0])
    7.                 xor         ebx,edx                                         ; ebx = ebx * sign(coef[0])
    8.                 sub         ebx,edx                                         ; ebx = displace(ebx)
    9.                 add         eax,ebx                                         ; eax = coef[0] + sign(coef[0]) * xquant/2
    10.                 idiv        ecx                                             ; eax = quantized coef[0]
    11.                 and         eax,0FFFFh                                      ; Mask high-order bits
    12.  
    13.                 movzx       ebx,word ptr quant                              ; ebx = quant
    14.                 ; Обработка 48 значений коеффициентов, с 16 по 63
    15.                 ; ..............................
    16.                 ; ..............................
    17.                 ; Обработка оставшихся  значений коеффициентов, с 0 по 15
    18.                 movq        mm0,coef[0 * 16 + 0]                            ; mm0 = [   C03      C02      C01        x ]
    19.                 movq        mm1,coef[0 * 16 + 8]                            ; mm1 = [   C07      C06      C05      C04 ]
    20.                 movq        mm2,coef[1 * 16 + 0]                            ; mm2 = [   C11      C10      C09      C08 ]
    21.                 movq        mm3,coef[1 * 16 + 8]                            ; mm3 = [   C15      C14      C13      C12 ]
    22.                 movq        mm4,mm0                                         ; mm4 = [   C03      C02      C01        x ]
    23.                 movq        mm5,mm1                                         ; mm5 = [   C07      C06      C05      C04 ]
    24.                 movq        mm6,mm2                                         ; mm6 = [   C11      C10      C09      C08 ]
    25.                 movq        mm7,mm3                                         ; mm7 = [   C15      C14      C13      C12 ]
    26.                 psraw       mm4,16                                          ; mm4 = sign(mm0)
    27.                 psraw       mm5,16                                          ; mm5 = sign(mm1)
    28.                 psraw       mm6,16                                          ; mm6 = sign(mm2)
    29.                 psraw       mm7,16                                          ; mm7 = sign(mm3)
    30.                 pxor        mm0,mm4                                         ; mm0 = abs(mm0)
    31.                 pxor        mm1,mm5                                         ; mm1 = abs(mm1)
    32.                 pxor        mm2,mm6                                         ; mm2 = abs(mm2)
    33.                 pxor        mm3,mm7                                         ; mm3 = abs(mm3)
    34.                 psubw       mm0,mm4                                         ; mm0 = displace(mm0)
    35.                 psubw       mm1,mm5                                         ; mm1 = displace(mm1)
    36.                 psubw       mm2,mm6                                         ; mm2 = displace(mm2)
    37.                 psubw       mm3,mm7                                         ; mm3 = displace(mm3)
    38.                 pmulhw      mm0,[reciprocals + 8 * ebx - 8]                 ; mm0 = mm0 / quant
    39.                 pmulhw      mm1,[reciprocals + 8 * ebx - 8]                 ; mm1 = mm1 / quant
    40.                 pmulhw      mm2,[reciprocals + 8 * ebx - 8]                 ; mm2 = mm2 / quant
    41.                 pmulhw      mm3,[reciprocals + 8 * ebx - 8]                 ; mm3 = mm3 / quant
    42.                 pxor        mm0,mm4                                         ; mm0 = mm0 * sign(mm0)
    43.                 pxor        mm1,mm5                                         ; mm1 = mm1 * sign(mm1)
    44.                 pxor        mm2,mm6                                         ; mm2 = mm2 * sign(mm2)
    45.                 pxor        mm3,mm7                                         ; mm3 = mm3 * sign(mm3)
    46.                 psubw       mm0,mm4                                         ; mm0 = displace(mm0)
    47.                 psubw       mm1,mm5                                         ; mm1 = displace(mm1)
    48.                 psubw       mm2,mm6                                         ; mm2 = displace(mm2)
    49.                 psubw       mm3,mm7                                         ; mm3 = displace(mm3)
    50.                 movd        mm5,eax                                         ; mm5 = [     0        0        0      C00 ]
    51.                 pxor        mm6,mm6                                         ; mm6 = [     0        0        0        0 ]
    52.                 pcmpeqw     mm6,mm5                                         ; mm6 = [  FFFF     FFFF     FFFF        0 ]
    53.                 pand        mm0,mm6                                         ; mm0 = [   C03      C02      C01        0 ]
    54.                 por         mm0,mm5                                         ; mm0 = [   C03      C02      C01      C00 ]
    55.                 movq        coef[0 * 16 + 0],mm0                            ; Save  [   C03      C02      C01      С00 ]
    56.                 movq        coef[0 * 16 + 8],mm1                            ; Save  [   C07      C06      C05      C04 ]
    57.                 movq        coef[1 * 16 + 0],mm2                            ; Save  [   C11      C10      C09      C08 ]
    58.                 movq        coef[1 * 16 + 8],mm3                            ; Save  [   C15      C14      C13      C12 ]
    59.  
    60.                 ; ...........................
    61.  
    62.                 endm
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    v_mirgorodsky
    Откуда у тебя берется 217 тиков не знаю. У меня на Nortwood'ах получается ~124 тика (repeat 4 раза куска от movq mm0 до movd mm5,eax). На Pentium D чуть хуже ~135 тиков (оба ядра вкл, дискретность rdtsc = 15 тиков)

    Что касается div\idiv, то в отличие от fdiv они содержат пару десятков мопов в порт 1, которые ес-но конфликтуют с mmx (см.табличку у А.Фога)

    PS: ты все jpeg мучаешь, или точнее он тебя ? ;))
     
  3. v_mirgorodsky

    v_mirgorodsky New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    53
    Угу, он меня в основном ;)

    По поводу "лишних" тактов - тоже почти разобрался. Оказывается пустой call с немедленным return, обрамленный rdtsc почему-то таймится на уровне 97 тиков прямо со старта. Не знаю с чем это связано, но нашел простой способ борьбы с этой напастью - просто дублирую тело изучаемого макроса в пределах функции большое (>30) количество раз. Естественно, полученные тики потом делю на количество повторов - тогда и получается результат более приближенный к реальности.

    idiv заменил на два умножения - одно для получения частного, второе - для вычисления остатка от деления. В итоге получил увеличение времени выполнения функции на 2 такта, в отличие от 25-30 с прямым idiv. Почувствовал разницу ;)