Я не могу понять, как реализовать:Найти 4 минимальные значения в 4 __m256d регистрирует
__m256d min(__m256d A, __m256d B, __m256d C, __m256d D)
{
__m256d result;
// result should contain 4 minimal values out of 16 : A[0], A[1], A[2], A[3], B[0], ... , D[3]
// moreover it should be result[0] <= result[1] <= result[2] <= result[2]
return result;
}
Любые идеи о том, как использовать _mm256_min_pd
, _mm256_max_pd
и перемешивает/переставляет в умный способ?
=============================================================================================================================================== ====
Это где я получил до сих пор, после того, как:
__m256d T = _mm256_min_pd(A, B);
__m256d Q = _mm256_max_pd(A, B);
A = T; B = Q;
T = _mm256_min_pd(C, D);
Q = _mm256_max_pd(C, D);
C = T; D = Q;
T = _mm256_min_pd(B, C);
Q = _mm256_max_pd(B, C);
B = T; C = Q;
T = _mm256_min_pd(A, B);
Q = _mm256_max_pd(A, B);
A = T; D = Q;
T = _mm256_min_pd(C, D);
Q = _mm256_max_pd(C, D);
C = T; D = Q;
T = _mm256_min_pd(B, C);
Q = _mm256_max_pd(B, C);
B = T; C = Q;
мы имеем: A [0] < B [0] < C [0] < D [0], [1] < В [1] < С [1] < D [1], А [2] < В [2] < С [2] < D [2], А [3] < B [3] < C [3] < D [3],
поэтому минимальное значение среди й, второй минимальный является одним из элементов а или Б, ... Не знает, куда идти оттуда ...
=============================================================================================================================================== ==========
Вторая идея заключается в том, что проблема сводима к себе, но с 2-мя входами __m256 элементами. Если это можно сделать, просто сделайте min4 (A, B) -> P, min4 (C, D) -> Q, min4 (P, Q) -> возвращаемое значение.
Понятия не имею, как к тому, что для двух векторов, хотя :)
=============================== =================================================
Обновление 2: проблема почти решена - следующая функция вычисляет 4 минимальных значения.
__m256d min4(__m256d A, __m256d B, __m256d C, __m256d D)
{
__m256d T;
T = _mm256_min_pd(A, B);
B = _mm256_max_pd(A, B);
B = _mm256_permute_pd(B, 0x5);
A = _mm256_min_pd(T, B);
B = _mm256_max_pd(T, B);
B = _mm256_permute2f128_pd(B, B, 0x1);
T = _mm256_min_pd(A, B);
B = _mm256_max_pd(A, B);
B = _mm256_permute_pd(B, 0x5);
A = _mm256_min_pd(A, B);
T = _mm256_min_pd(C, D);
D = _mm256_max_pd(C, D);
D = _mm256_permute_pd(D, 0x5);
C = _mm256_min_pd(T, D);
D = _mm256_max_pd(T, D);
D = _mm256_permute2f128_pd(D, D, 0x1);
T = _mm256_min_pd(C, D);
D = _mm256_max_pd(C, D);
D = _mm256_permute_pd(D, 0x5);
C = _mm256_min_pd(C, D);
T = _mm256_min_pd(A, C);
C = _mm256_max_pd(A, C);
C = _mm256_permute_pd(C, 0x5);
A = _mm256_min_pd(T, C);
C = _mm256_max_pd(T, C);
C = _mm256_permute2f128_pd(C, C, 0x1);
T = _mm256_min_pd(A, C);
C = _mm256_max_pd(A, C);
C = _mm256_permute_pd(C, 0x5);
A = _mm256_min_pd(A, C);
return A;
};
Осталось только отсортировать значения в порядке возрастания внутри А перед возвратом.
В чем конкретная проблема, с которой вы столкнулись? Это довольно широкий вопрос. –
Вы ищете тот, который получает самые низкие 4 удваивания из всех 16 двойников в один вектор, по порядку, правильно? Сеть сортировки Google SIMD и тому подобное. Вы можете обнаружить, что распаковка двух векторов '__m128d' полезна для некоторых шагов, но, возможно, нет. Если вы заботитесь только о наименьших 4 элементах, а не о полном виде, сложнее сканировать скалярный код с помощью сортировочной сети SIMD. –
Правильно - самый низкий из 4 удваивает из всех 16 двойников в один вектор. Эти 4 вектора содержат 16 значений, которые являются результатом вычисления SIMD, которое работает очень хорошо. В конце должны быть выбраны 4 наименьших. Цель состоит не в том, чтобы бить скалярный код, а только для того, чтобы его избежать. Мне кажется нелогичным выгружать значения в память, затем сортировать, а затем снова загружать. –