2016-07-12 14 views
0

У меня есть 256-битный регистр AVX, содержащий 4 одиночных прецизионных комплексных номера, хранящихся как реальные, мнимые, реальные, мнимые и т. Д. В настоящее время я записываю весь 256-битный регистр обратно в память и суммирую его там, но это кажется неэффективным.AVX, Горизонтальная сумма одиночных прецизионных комплексных номеров?

Как выполнить горизонтальную сумму комплексного числа с использованием свойств AVX (или AVX2)? Я бы принял ответ, используя сборку, если нет ответа с сопоставимой эффективностью с использованием встроенных функций.

Редактировать: Чтобы уточнить, если регистр содержит AR, AI, BR, BI, CR, CI, DR, DI, я хочу вычислить комплексное число (AR + BR + CR + DR, AI + BI + CI + DI). Если результат находится в 256-битном регистре, я могу извлечь 2 числа с плавающей запятой с одной точностью.

Edit2: Потенциальное решение, хотя и не обязательно оптимален ...

float hsum_ps_sse3(__m128 v) { 
    __m128 shuf = _mm_movehdup_ps(v);  // broadcast elements 3,1 to 2,0 
    __m128 sums = _mm_add_ps(v, shuf); 
    shuf  = _mm_movehl_ps(shuf, sums); // high half -> low half 
    sums  = _mm_add_ss(sums, shuf); 
    return  _mm_cvtss_f32(sums); 
} 

float sumReal = 0.0; 
float sumImaginary = 0.0; 

__m256i mask = _mm256_set_epi32 (7, 5, 3, 1, 6, 4, 2, 0); 

// Separate real and imaginary. 
__m256 permutedSum = _mm256_permutevar8x32_ps(sseSum0, mask); 
__m128 realSum = _mm256_extractf128_ps(permutedSum , 0); 
__m128 imaginarySum = _mm256_extractf128_ps(permutedSum , 1); 

// Horizontally sum real and imaginary. 
sumReal = hsum_ps_sse3(realSum); 
sumImaginary = hsum_ps_sse3(imaginarySum); 
+0

Мы сайт кода; вы можете объяснить, что вам проще с простым примером. Тем не менее, мне не хватает этой проблемы. Да, AVX - безумный дизайн с двумя полосами, но в этом случае это не повредит. Перемешайте реальные части на одну полосу, воображаемые компоненты на другую полосу (бит 0: 127 и 128: 255), сделайте горизонтальное добавление в пределах полосы. Результаты заканчиваются в 0:31 и 128: 159. – MSalters

+0

Какую цель? Возможно, вы хотите рассмотреть возможность хранения восьми комплексных чисел в двух регистрах AVX: реальные части в одной и мнимой частях в другой. Это действительно зависит от вашей цели. –

+0

@ Zboson Моя цель точно такая же, как указано в вопросе. Данные хранятся так, что реальные и мнимые значения чередуются, и это невозможно изменить. Решение, которое я предложил в моем редактировании, разделяет реальные и мнимые компоненты, чтобы суммировать их, но входные данные будут чередоваться реальными и мнимыми. – user1777820

ответ

3

Одно довольно простое решение, которое требует только AVX (не AVX2):

__m128i v0 = _mm256_castps256_ps128(v);  // get low 2 complex values 
__m128i v1 = _mm256_extractf128_ps(v, 1); // get high 2 complex values 
v0 = _mm_add_ps(v0, v1);      // add high and low 
v1 = _mm_shuffle_ps(v0, v0, _MM_SHUFFLE(1, 0, 3, 2)); 
v0 = _mm_add_ps(v0, v1);      // combine two halves of result 

Результат будет v0 как { sum.re, sum.im, sum.re, sum.im }.

+0

Странно - что-то связанное с завершением линии CR/LF? –

+0

Hahaha ... Я использую случайный агент Spoofer в Firefox, который я недавно установил, чтобы опробовать. Видимо, профиль, который он произвольно выбирал, сделал это (я думаю, это был IE10). Когда я выбираю новый случайный профиль, он отображается правильно. –

+0

Ага - это рельеф, тогда - я ударил [править] раньше и не мог видеть ничего плохого с сообщением. –