имеется алгоритм быстрой сортировки 8-байтового массива и 16-байтового узкое место - свап элементов а = [eax+esi*SIZE] b = [eax+edi*SIZE] Вопрос. Как быстро осуществить свап ? Я делаю так (для 8 байт) Код (Text): mov ecx, [eax+esi*8] mov edx, [eax+edi*8] mov [eax+edi*8], ecx mov [eax+esi*8], edx mov edx, [eax+edi*8+4] mov ecx, [eax+esi*8+4] mov [eax+esi*8+4], edx mov [eax+edi*8+4], ecx
MMX/SSE я не знаю как это будет выглядеть ? ещё вопрос. Разумно ли использовать MMX/SSE для свапа ? переход из "обычного режима" в MMX/SSE, как я слышал, медленный. и для разового использования нецелесообразно
Такой переход нужно делать только для MMX в конце сортировки. Цель оправдывает средства. MMX Код (Text): movq mm0,[eax+esi*8] movq mm1,[eax+edi*8] movq [eax+esi*8],mm1 movq [eax+edi*8],mm0 По окончании сортировки нужно будет выполнить EMMS. SSE Код (Text): movups xmm0,[eax+esi*8] movups xmm1,[eax+edi*8] movups [eax+esi*8],xmm1 movups [eax+edi*8],xmm0 Но лучше будет выравнять массив по границе 16 байт и использовать movaps.
Большое спасибо ! murder, первый случай для восьми байт, второй для 16 ? EMMS в конце MMX и SSE ? Для обоих случаев работает ? В случае 16 байт и esi/edi кратным двойке нормально будет так ? test eax, 15 jz @1 movups xmm0,[eax+esi*8] movups xmm1,[eax+edi*8] movups [eax+esi*8],xmm1 movups [eax+edi*8],xmm0 jmp @2 @1: movaps xmm0,[eax+esi*8] movaps xmm1,[eax+edi*8] movaps [eax+esi*8],xmm1 movaps [eax+edi*8],xmm0 @2:
Sol_Ksacap, Код (Text): asm push ebx mov eax, 1 cpuid test edx, 02000000h jz @Done mov [SSE], 1 test edx, 04000000h jz @Done mov [SSE2], 1 @Done: pop ebx end;
Здравствуйте, друзья только сейчас занялся оптимизацией и понял, что MMX-вариант работает в 2.5 раза медленнее, чем обычный почему? размер массива - 100 элементов (по 16 байт каждый) Код (Text): procedure InvertArray16_MMX(var DynArray); asm mov eax, [eax] test eax, eax jz @exit; mov ecx, [eax-4] {$ifdef fpc} inc ecx {$endif} cmp ecx, 1 jle @exit // eax - left // edx - right // ecx - count // mm0, mm1 - buffers lea edx, [ecx*8] lea edx, [eax+edx*2-16] shr ecx, 1 @loop: // swap eax <--> edx movq mm0,[eax] movq mm1,[edx] movq [eax],mm1 movq [edx],mm0 movq mm0,[eax+8] movq mm1,[edx+8] movq [eax+8],mm1 movq [edx+8],mm0 add eax, 16 sub edx, 16 dec ecx jnz @loop EMMS @exit: end; procedure InvertArray16_NORM(var DynArray); asm mov eax, [eax] test eax, eax jz @exit; mov ecx, [eax-4] {$ifdef fpc} inc ecx {$endif} cmp ecx, 1 jle @exit // eax - left // edx - right // ecx - count // edi, esi - buffers push esi push edi //lea edx, [eax+ecx*16-16] lea edx, [ecx*8] lea edx, [eax+edx*2-16] shr ecx, 1 @loop: // swap eax <--> edx mov esi, [eax] mov edi, [edx] mov [eax], edi mov [edx], esi mov esi, [eax+4] mov edi, [edx+4] mov [eax+4], edi mov [edx+4], esi mov esi, [eax+8] mov edi, [edx+8] mov [eax+8], edi mov [edx+8], esi mov esi, [eax+12] mov edi, [edx+12] mov [eax+12], edi mov [edx+12], esi add eax, 16 sub edx, 16 dec ecx jnz @loop pop edi pop esi @exit: end;
edemko, это delphi-функции там в динамических массивах [указатель - 4] - количество элементов P.S. странно, но теперь MMX-вариант работает быстрее так и не понял почему
s:WideString; i:dword; i:=length(s); примерно, ибо не помню: mov eax, mov eax,[eax-4] shr eax,1 ;число байт в число wChar-символов mov ,1 ;число БАЙТ(редактировал) / число байт в элементе(2 для wChar) Посему и спрашивал, не надо ли там: shr ecx,3 // делить на 8 и узнать число элементов shr ecx,1 // число шагов для цикла реверсирования //или shr ecx,4 // вместо двух shr выше jz @exit // пустой масив
emms можно лишний раз не использовать, только перед задействованием инструкций FPU, но делфи, кажись, такого не ожидает и чего-то пишет об этом, ничего уже не помню толком.
edemko, WideString - это единственное исключение во всех остальных случаях - количество элементов. Для FreePascal в [указатель - 4] хранится High массива, т.е. Length-1
DevilDevil А тестовые массивы для сортировки небось заполняешь случайными числами и каждый раз разными? Следи чтобы оба варианта тестировались на одинаковых исходных данных ЗЫ: сам на этом обжигался.
Масив сортируют?, если да, то даже на GP(простых инструкциях) будет упадок: всякое сравнение решает, писать ему или нет. mmx флагов не устанавливает, отсюда задержка на проверку даже больше от GP, хотя их размер 2xDWORD может компенсировать. Ну, я наверно не понял. Попробуйте GetTickCount на входе в тело и выходе.