Как получить данные из регистров AVX?

Используя MSVC 2013 и AVX 1, у меня есть 8 поплавков в регистре:

__m256 foo = mm256_fmadd_ps(a,b,c);

Теперь я хочу позвонитьinline void print(float) {...} на все 8 поплавков. Похоже,Intel AVX intrisics сделает это довольно сложным:

print(_castu32_f32(_mm256_extract_epi32(foo, 0)));
print(_castu32_f32(_mm256_extract_epi32(foo, 1)));
print(_castu32_f32(_mm256_extract_epi32(foo, 2)));
// ...

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

Бонус Q: я бы конечно хотел написать

for(int i = 0; i !=8; ++i) 
    print(_castu32_f32(_mm256_extract_epi32(foo, i)))

но MSVC не понимает, что много внутреннихтребовать развернуть петлю. Как мне написать цикл над 8x32 плавает в__m256 foo?

 MSalters04 июн. 2016 г., 01:00
@PeterCordes: На самом деле, я представил здесь AVX, потому что это общий шаблон. Фактические вызовы все встроенные, в 20-50 самих инструкциях,но некоторые из них по очереди вызывают не встроенные функции. Но AVX не уходит, и я не могу быть единственным, кто собирается связать SIMD-код AVX с классическим SISD-кодом, поэтому общий ответ приветствуется.
 Marc Glisse03 июн. 2016 г., 20:49
Если вы заботитесь только о MSVC, что-то вродеfoo.m256_f32[i] может работать (то естьfoo[i] с gcc).
 Peter Cordes03 июн. 2016 г., 20:44
Имеет ли значениеprint() заменяет функцию, которая действительно может быть полностью встроенной, или если компиляторуcall функция, для которой не виден код. Что на самом деле происходит?
 MSalters03 июн. 2016 г., 13:19
@PaulR: упрощенный пример.
 Paul R03 июн. 2016 г., 13:12
Если вы собираетесь печатать данные, то вряд ли имеет значение разливать регистр в память - просто используйте подходящий союз.
 MSalters04 июн. 2016 г., 02:23
@PeterCordes: у меня есть рекурсивный шаблон кода для идеи Пола. Развертывание не требуется; просто выделение из 7 уровней вспомогательных функций. Довольно просто на самом деле - один звонокprintодин рекурсивный вызов. Должно быть тривиально встроенным, что означает, что я получаю 8 вызовов подряд, как с развернутым циклом. Все еще должен проверить сборку все же.
 Peter Cordes04 июн. 2016 г., 01:42
@MSalters: я думаю, что мой ответ довольно хорошо охватывает оба случая: оптимальный шаблон для перетаскивания данных в отдельные регистры xmm, и когда лучше хранить store + scalar-load (то есть для целых чисел или при вызове функций, которые будут перекрывать векторные регистры). Вообще хранение в памяти для этого не плохо; задержка при пересылке магазина на процессорах Intel составляет всего около 5 с. Это плохо только для горизонтальной суммы или другого сокращения. Я работаю над вторым ответом о стороне C ++ и об удобном синтаксисе для зацикливания векторных элементов. (например, GCC развертывается для вас с-O1 или выше)

Ответы на вопрос(0)

Ваш ответ на вопрос