Обеспечение того, чтобы Eigen использовал AVX-векторизацию для определенной операции - PullRequest
7 голосов
/ 13 января 2020

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

Я также проверил, что AVX включен, убедившись, что EIGEN_VECTORIZE_AVX определяется после включения Eigen.

Однако кажется, что моя функция никогда не вызывается с Packet8f (AVX), если размер данных не кратен 8. Вместо этого она вызывается с Packet4f (SSE).

Вот небольшое замечание: https://gist.github.com/bitonic/e89561cb21837b4dee8b5f49e1303919. Здесь я определяю операцию, используя Packet4f и Packet8f, а затем подсчитываю, сколько раз каждый вызывается с массивом размером 8 и 9. Когда массив имеет размер 8, версия Packet8f вызывается один раз, как ожидается. Когда он имеет размер 9, версия Packet4f вызывается дважды вместо одного вызова не векторизованной версии. Я проверил этот код на текущем мастере Эйгена 1d0c45122a5c4c5c1c4309f904120e551bacad02.

Я немного откопал и считаю, что здесь происходит выбор пакета: https://gitlab.com/libeigen/eigen/blob/1d0c45122a5c4c5c1c4309f904120e551bacad02/Eigen/src/Core/util/XprHelper.h#L197.

Если я правильно понимаю, если размер данных не является динамическим c и не кратным 8 (это значение unpacket_traits<Packet8f>::size), будет выбран полупакет, который соответствует тому, что показано выше для воспроизведения .

Если мое понимание верно, почему это так? Разве не должен быть выбран полный пакет с оставшимися элементами, работающими с невекторизованной операцией?

Может ли быть, что это условие неверно, и вместо этого должно быть сравнение> =, например, что-то вроде

template<int Size, typename PacketType,
         bool Stop = Size==Dynamic || Size >= unpacket_traits<PacketType>::size || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
struct find_best_packet_helper;

вместо

template<int Size, typename PacketType,
         bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
struct find_best_packet_helper;

Я убедился, что с исправлением, описанным выше, проблема исчезает.

Однако я могу неправильно понять, что здесь происходит, так как Я не очень хорошо разбираюсь во внутренних органах Eigen.

1 Ответ

3 голосов
/ 20 января 2020

Я подтвердил, что это связано с тем, как Eigen выбирает тип пакета, см. https://gitlab.com/libeigen/eigen/merge_requests/46 для исправления.

...