Найти наиболее значимый DWORD в массиве DWORD - PullRequest
2 голосов
/ 12 апреля 2011

Я хочу найти самый значимый DWORD, который не равен 0 в массиве DWORD.Алгоритм должен быть оптимизирован для данных размером до 128 байт.

Я сделал три разные функции, которые все возвращают индекс определенного DWORD.

unsigned long msb_msvc(long* dw, std::intptr_t n)
{
    while( --n )
    {
        if( dw[n] )
            break;
    }
    return n;
}

static inline unsigned long msb_386(long* dw, std::intptr_t n)
{
    __asm 
    {
        mov ecx, [dw]
        mov eax, [n]

__loop: sub eax, 1
        jz  SHORT __exit
        cmp DWORD PTR [ecx + eax * 4], 0
        jz  SHORT __loop
__exit:
    }
}

static inline unsigned long msb_sse2(long* dw, std::intptr_t n)
{
    __asm 
    {
        mov  ecx, [dw]
        mov  eax, [n]
        test ecx, 0x0f
        jnz  SHORT __128_unaligned

__128_aligned:
        cmp      eax, 4
        jb       SHORT __64
        sub      eax, 4
        movdqa   xmm0, XMMWORD PTR [ecx + eax * 4]
        pxor     xmm1, xmm1
        pcmpeqd  xmm0, xmm1
        pmovmskb edx, xmm0
        not      edx
        and      edx, 0xffff
        jz       SHORT __128_aligned
        jmp      SHORT __exit

__128_unaligned:
        cmp      eax, 4
        jb       SHORT __64
        sub      eax, 4
        movdqu   xmm0, XMMWORD PTR [ecx + eax * 4]
        pxor     xmm1, xmm1
        pcmpeqd  xmm0, xmm1
        pmovmskb edx, xmm0
        not      edx
        and      edx, 0xffff
        jz       SHORT __128_unaligned
        jmp      SHORT __exit

__64:
        cmp      eax, 2
        jb       __32
        sub      eax, 2
        movq     mm0, MMWORD PTR [ecx + eax * 4]
        pxor     mm1, mm1
        pcmpeqd  mm0, mm1
        pmovmskb edx, mm0
        not      edx
        and      edx, 0xff
        emms
        jz       SHORT __64
        jmp      SHORT __exit

__32:
        test eax, eax
        jz   SHORT __exit
        xor  eax, eax
        jmp  __leave ; retn

__exit:
        bsr      edx, edx
        shr      edx, 2
        add eax, edx

__leave:
    }
}

Эти функции должны бытьиспользуется для предварительного выбора данных, которые будут сравниваться друг с другом.Итак, он должен быть быстродействующим.

Кто-нибудь знает лучший алгоритм?

1 Ответ

1 голос
/ 12 апреля 2011

Я думаю, вы просто ищете первое ненулевое слово в данном массиве. Я бы определенно пошел с простым циклом, написанным на C. Если есть какая-то причина, почему это super критично для производительности, я бы порекомендовал вам взглянуть в более широком контексте вашей программы и спросить, например вопрос, почему вам нужно найти ненулевой объект из массива и почему вы не можете знать его местонахождение уже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...