неразрешенный внешний символ __mm256_setr_epi64x

Я написал и отладил некоторый код AVX с помощью g ++, и теперь я пытаюсь заставить его работать с MSVC, но продолжаю получать

ошибка LNK2019: неразрешенный внешний символ __mm256_setr_epi64x, указанный в функции «private: union __m256i __thiscall avx_matrix :: avx_bit_mask (unsigned int) const» (? avx_bit_mask @ avx_matrix @@ ABE? AT__m256i @@ I @ Z)

Указанный фрагмент кода

...

#include <immintrin.h>

...

    /* All zeros except for pos-th position (0..255) */
    __m256i avx_matrix::avx_bit_mask(const std::size_t pos) const
    {
        int64_t a = (pos >= 0 && pos < 64) ? 1LL << (pos - 0) : 0;
        int64_t b = (pos >= 64 && pos < 128) ? 1LL << (pos - 64) : 0;
        int64_t c = (pos >= 128 && pos < 192) ? 1LL << (pos - 128) : 0;
        int64_t d = (pos >= 192 && pos < 256) ? 1LL << (pos - 256) : 0;
        return _mm256_setr_epi64x(a, b, c, d);
    }
...
  • Я включил /arch:AVX, но это не имеет значения.
  • Моя машина определенно поддерживает AVX - это тот же самый, что я использовал для исходного проекта Linux.
  • Кроме того, http://msdn.microsoft.com/en-us/library/hh977022.aspx перечисляет _mm256_setr_epi64x среди доступных встроенных функций.

Любая помощь приветствуется.


person PJK    schedule 02.12.2014    source источник


Ответы (2)


Похоже, это действительно может быть известная ошибка - некоторые встроенные функции AVX, по-видимому, недоступны в 32-битном режиме. Попробуйте выполнить сборку для 64-разрядной версии и / или выполнить обновление до Visual Studio 2013 с обновлением 2, где это предположительно теперь исправлено.

В качестве альтернативы, если у вас есть только один экземпляр выше, в котором вы используете эту встроенную функцию, вы можете изменить свою функцию на:

__m256i avx_matrix::avx_bit_mask(const std::size_t pos) const
{
    int64_t a[4] = { (pos >=   0 && pos <  64) ? 1LL << (pos -   0) : 0,
                     (pos >=  64 && pos < 128) ? 1LL << (pos -  64) : 0,
                     (pos >= 128 && pos < 192) ? 1LL << (pos - 128) : 0,
                     (pos >= 192 && pos < 256) ? 1LL << (pos - 256) : 0 };
    return _mm256_loadu_si256((__m256i *)a);
}

или, возможно, даже:

__m256i avx_matrix::avx_bit_mask(const std::size_t pos) const
{
    int64_t a[4] = { 0 };
    a[pos >> 6] = 1LL << (pos & 63ULL);
    return _mm256_loadu_si256((__m256i *)a);
}

который может быть немного более эффективным.

person Paul R    schedule 02.12.2014
comment
В вашей ссылке указано, что это соединение является ненадежным. - person Z boson; 03.12.2014
comment
Хех - похоже, Microsoft забыла обновить свой сертификат. - person Paul R; 03.12.2014
comment
Хорошо +1 за обнаружение, что это якобы было исправлено. Однако это 2014 год. Кто на самом деле больше использует 32-битный режим? OS X сейчас только 64-битная. Ubuntu постепенно откажется от 32-разрядной версии через год. MSFT должна была исправить это 8 лет назад. - person Z boson; 03.12.2014
comment
Люди часто застревают в 32-битной версии Windows по разным причинам: сторонние 32-битные библиотеки, использование встроенного ассемблера, устаревший код, который не является 64-битным чистым, и т. Д. Но это лишь одна из многих причин, по которым я избегаю Вся токсичная экосистема Microsoft, насколько это возможно - я буду придерживаться OS X и Linux, спасибо. - person Paul R; 03.12.2014
comment
Несколько месяцев назад я отказался от MSVC. Он не так хорош для оптимизации и любит делать много разных вещей по-другому, например. он определяет только __AVX__ и __AVX2__. Он поддерживает OpenMP только с 2003 года. Когда я преобразовал свой фрактальный код для использования FMA с MSVC, он был намного медленнее, чем без FMA. С GCC это было быстрее. - person Z boson; 03.12.2014
comment
Ваше решение с использованием _mm256_loadu_si256 явно лучше моего. Я не думал об этом внимательно. Конечно, я бы никогда не использовал свое решение в основном цикле. Я сконцентрировался на внутреннем. Этот вопрос был бы лучше, если бы он спрашивал, как эффективно установить отдельный бит с учетом индекса. - person Z boson; 03.12.2014
comment
Ну, я не был уверен, нужно ли OP общее решение для нескольких экземпляров _mm256_setr_epi64x или это было всего лишь одноразовым, но да, надеюсь, ничего из этого не происходит внутри критических для производительности циклов, поэтому любое решение, которое работает все должно быть в порядке. - person Paul R; 03.12.2014

В 32-битном режиме MSVC не поддерживает

  • _mm_set_epi64x
  • _mm_setr_epi64x
  • _mm_set1_epi64x
  • _mm256_set_epi64x
  • _mm256_setr_epi64x
  • _mm256_set1_epi64x

В вашем случае в 32-битном режиме вы можете сделать это:

    union {
        int64_t q[4];
        int32_t r[8];
    } u;
    u.q[0] = a; u.q[1] = b; u.q[2] = c; u.q[3] = d;
    return _mm256_setr_epi32(u.r[0], u.r[1], u.r[2], u.r[3], u.r[4], u.r[5], u.r[6], u.r[7]);

Начиная с Visual Studio 2015 (_MSC_VER 1900) эти встроенные функции поддерживаются в 32-битном режиме.

person Z boson    schedule 03.12.2014
comment
Я считаю, что то, как вы используете объединение, - это неопределенное поведение в C ++. - person jww; 12.02.2019
comment
@jww, можете ли вы предоставить ссылку (например, из SO), объясняющую, почему вы думаете, что это UB? - person Z boson; 12.02.2019
comment
@jww, я прочитал некоторые ответы по этой ссылке и запутался. Не стесняйтесь дополнять мой ответ. (пожалуйста, не удаляйте ничего, добавляйте только новую информацию после того, что у меня есть сейчас), если вам нравится решение, которое, по вашему мнению, не является UB. - person Z boson; 13.02.2019
comment
@jww, я полагаю, использование memcpy - более безопасное (но даже более неэффективное) решение? - person Z boson; 13.02.2019
comment
@jww: Microsoft определяет поведение такого кода в MSVC; они даже определяют __m256i в терминах подобного союза. Также существует расширение GNU (gcc / clang / icc), которое определяет поведение каламбура типа union в GNU C ++ и C89. (Это уже четко определено в ISO C99 / C11) - person Peter Cordes; 13.02.2019
comment
Я почти уверен, что все основные компиляторы явно поддерживают каламбур типа union в стиле C для C ++, даже если он технически не определен в C ++. - person Mysticial; 14.02.2019