2016-10-14 1 views
4

Как видно из названия читает, если 256-битный SIMD-регистр:Есть ли эффективный способ получить первый ненулевой элемент в регистре SIMD с использованием SIMD-функций?

0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |

Как можно эффективно получить индекс первого ненулевого элемента (т.е. индекса 2 первых 1)? Самый простой способ - хранить в памяти и проверять один за другим, но это может стоить много. Есть ли какие-нибудь симпатичные идеи?

ответ

7
  • PCMPEQB/W/D/Q против регистра с нулевым нулем, чтобы получить вектор с элементами, которые все-1 для нулевых элементов и все-нулевые для нулевых элементов.
  • PMOVMSKB повернуть вектор всех-оны или все нулевой в целое число битовой маски
  • инвертных, что (С ~ оператором, ASM НЕ инструкция), чтобы получить 1s в битовой карте для элементов, которые были ненулевых
  • TZCNT или BSF, чтобы целое число находило первый бит набора. Остерегайтесь поведения BSF, если его ввод равен нулю.

Если есть только один возможный ненулевое значение, PCMPEQ против вектора, что Вам не нужно, чтобы инвертировать его позже.

Если это так, подумайте о сохранении ваших данных в растровых изображениях в первую очередь, чтобы уменьшить размер кеша в 8 раз. Тогда вы просто TZCNT 64-разрядные куски массива.


oops, только что заметил тег intrinsics. В справочном руководстве по инструкции ASM перечислены соответствующие C-функции в нижней части каждой записи, и вы можете искать встроенный искатель Intel по asm-мнемонике. (Смотрите ссылки на теги ).

+0

спасибо @Peter. Я думаю, вы имеете в виду 'LZCNT' вместо' TZCNT'. По сути, идеи asm лучше, и в любом случае спасибо за информацию об интригах. Как вы уже упоминали, существует только одно возможное ненулевое значение, но любая идея, как реализовать на уровне сборки в отношении проблемы с кешем? – MarZzz

+0

@MarZzz: высокий бит элемента 0 (сначала arg '_mm_set_epi8', последний аргумент' _mm_setr_epi8') переходит в LSB целочисленной маски. TZCNT/BSF сначала смотрят на младший бит, поэтому их сканирование выполняется с низкого адреса на высокий адрес (если вектор был загружен из памяти). Если вы хотите сканировать в другом направлении, используйте LZCNT или BSR (которые дают разные результаты). –

+0

@MarZzz: Что не очевидно в реализации растрового изображения в asm? Для этого варианта использования 'tzcnt rax, [my_bitmap + rsi]' или что-то еще, чтобы увидеть, есть ли какие-либо удары в 64 битах, начиная с 8 * rsi (поскольку память по-прежнему байт-адресована, если вы не используете BT/BTR/BTS, но не потому, что они супер-медленны с операндами памяти, см. Http://agner.org/optimize/) –

Смежные вопросы