Для конкретного проекта я остановился на 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 long, которые влияют на регистры в таком
способ:
uint64 a, b;
__asm__ volatile (“POPCNT %1, %0;”
:”=r”(b)
:”r”(a)
:
)
gcc сообщает "несоответствие типа операнда для popcnt",
- а запись POPCNTQ приводит к «недопустимому суффиксу инструкции для popcnt».
Было бы так здорово, если бы POPCNT поддерживал 128-битные регистры xmm...
Есть ли обходной путь для применения POPCNT к 64-битным данным в сборке?
PS: обсуждение подсчета всплывающих окон SSSE3 с использованием перемешивания по сравнению с производительностью SSE4 POPCNT завершилось здесь http://danluu.com/assembly-intrinsics/ и было связано только с тем, что использование встроенных функций не всегда обеспечивает эффективный ассемблерный код. Приятно использовать встроенные функции для быстрой оптимизации кода C/C++, и если этого достаточно для удовлетворения потребностей, прекрасно. Но в остальном я получил почти 30-процентное улучшение производительности при кодировании всплывающего подсчета с использованием перетасовки в ассемблере по сравнению со встроенным.
"r"(a)
кажется невинным синтаксисом, он требует, чтобыa
соответствовал регистру GP. - person MSalters   schedule 26.01.2015