Как использовать инструкцию POPCNT для сборки при работе на 32-битной Ubuntu

Для конкретного проекта я использую gcc и 32-битную 12.04 LTS Ubuntu, работающую на i7 Core с поддержкой инструкций AVX SIMD.

Из-за 32-битной ОС я, очевидно, не могу использовать инструкции AVX, работающие на 256-битной версии. У меня есть доступ к инструкциям SSE4.2 с использованием 128 битов, и POPCNT может работать с 16, 32 и 64 битными данными, поэтому выглядело многообещающе. Но я попробовал несколько способов предоставить 64-битные данные в POPCNT без успеха. GCC 4.6.3 возвращает

  • "Неизвестное имя регистра" для r8 до r15,
  • "Неправильное имя реестра" для rax-rdx,
  • при попытке предоставить регистры mm или дать моей встроенной функции сборки некоторую длину uint64 или long, которые влияют на регистры в такой

путь:

uint64 a, b;
__asm__ volatile (“POPCNT %1, %0;”
            :”=r”(b)
            :”r”(a)
            :
        )

gcc сообщает "несоответствие типов операндов для popcnt",

  • и запись POPCNTQ приводит к "неверному суффиксу инструкции для popcnt".

Было бы так здорово, если бы POPCNT поддерживал 128-битные регистры xmm...

Любой обходной путь для применения POPCNT на 64-битных данных в сборке?

PS: обсуждение использования попсового счетчика SSSE3 с использованием shuffle по сравнению с производительностью SSE4 POPCNT пришло к заключению здесь http://danluu.com/assembly-intrinsics/ и было связано только с тем фактом, что использование встроенных функций не всегда обеспечивает эффективный код сборки. Хорошо использовать встроенные функции для быстрой оптимизации кода C/C++, и если этого достаточно для удовлетворения потребностей, хорошо. Но в остальном я получил почти 30% -ное улучшение производительности при программировании с использованием shuffle в сборке по сравнению с внутренним.

4 ответа

64-битный POPCOUNT не поддерживается в 32-битных системах, потому что

Префикс REX доступен только в длинном режиме. (не в 32-битной ОС)

следовательно

и запись POPCNTQ приводит к "неверному суффиксу инструкции для popcnt".

см. здесь: http://www.felixcloutier.com/x86/POPCNT.html (цитата ниже)

Opcode          Instruction         Op/En   64-Bit Mode  Compat/Leg Mode    Description
F3 0F B8 /r     POPCNT r16, r/m16   RM      Valid        Valid           POPCNT on r/m16
F3 0F B8 /r     POPCNT r32, r/m32   RM      Valid        Valid           POPCNT on r/m32
F3 REX.W 0F B8 /r POPCNT r64,r/m64  RM      Valid        N.E.            POPCNT on r/m64

Обходным путем будет разделить 64/128 бит на две / четыре 32-битные инструкции:

; a=uint_64, 64 bit operand, little endian
popcount eax, dword ptr [a]
popcount edx, dword ptr [a+4]
add eax, edx
xor edx, edx      ; for first mov below
mov dword ptr [b], edx      ; not neccessary, only due to 64 target op (will there ever be 2^64 bits set???)
mov dword ptr [b+4], eax

РЕДАКТИРОВАТЬ: 64-битная версия размера операнда (двоичного) HammingDistance в коде MASM32:

Hamming_64 PROC word1:QWORD , word2: QWORD
  mov ecx, dword ptr [word1]
  mov edx, dword ptr [word1+4]
  xor ecx, dword ptr [word2]
  xor edx, dword ptr [word2+4]
  popcnt eax, ecx 
  popcnt ebx, edx
  add eax, ebx   ; returns distance in EAX
  ret
Hamming_64 ENDP

popcnt целочисленная инструкция Таким образом, в 32-битном режиме вы не можете использовать его с 64-битными операндами. Вам нужно будет вычислить popcnt для двух половинок и сложите их вместе. Это то, что все версии Clang, которые я тестировал, делают для встроенного. Тем не менее, я не мог заставить какую-либо версию gcc использовать инструкцию popcnt. Таким образом, хотя обычно рекомендуется встроенная функция, в этом случае встроенный asm может быть лучше.

Я не знаю, есть ли 32-битная команда popcnt, но держу пари, что вы не можете использовать 64-битную popcnt в 32-битном коде. Попробуйте объявить a и b как uint32_t. Кстати, uint64_t - это стандартная версия C, а uint64 - нет.

После реализации 32-битного POPCNT с использованием сборки, похоже, что по сравнению с методом сборки в случайном порядке SSSE3 реального улучшения нет. Как я и подозревал, только 64-битная версия POPCNT может почти удвоить скорость.

Другие вопросы по тегам