gpt4 book ai didi

c++ - 使用 SSE 和 AVX 查找矩阵中的最大元素及其列和行索引

转载 作者:搜寻专家 更新时间:2023-10-31 00:31:32 25 4
gpt4 key购买 nike

我需要找到一维矩阵中的最大元素及其列索引和行索引。

我用的是一维矩阵,所以只需要先找到最大元素的索引,然后很容易得到行和列。

我的问题是我无法获取该索引。

我有一个找到最大元素并使用 SSE 的工作函数,这里是:

float find_largest_element_in_matrix_SSE(float* m, unsigned const int dims)
{
size_t i;
int index = -1;
__m128 max_el = _mm_loadu_ps(m);
__m128 curr;

for (i = 4; i < dims * dims; i += 4)
{
curr = _mm_loadu_ps(m + i);
max_el = _mm_max_ps(max_el, curr);
}

__declspec(align(16))float max_v[4] = { 0 };
_mm_store_ps(max_v, max_el);

return max(max(max(max_v[0], max_v[1]), max_v[2]), max_v[3]);
}

而且我还有一个使用 AVX 的非工作函数:

float find_largest_element_in_matrix_AVX(float* m, unsigned const int dims)
{
size_t i;
int index = -1;
__m256 max_el = _mm256_loadu_ps(m);
__m256 curr;

for (i = 8; i < dims * dims; i += 8)
{
curr = _mm256_loadu_ps(m + i);
max_el = _mm256_max_ps(max_el, curr);
}

__declspec(align(32))float max_v[8] = { 0 };
_mm256_store_ps(max_v, max_el);

__m256 y = _mm256_permute2f128_ps(max_el, max_el, 1);
__m256 m1 = _mm256_max_ps(max_el, y);m1[1] = max(max_el[1], max_el[3])
__m256 m2 = _mm256_permute_ps(m1, 5);
__m256 m_res = _mm256_max_ps(m1, m2);

return m[0];
}

谁能帮我找到最大元素的索引并让我的 AVX 版本正常工作?

最佳答案

这是一个有效的 SSE (SSE 4) 实现,它返回最大 val 和相应的索引,以及一个标量引用实现和测试工具:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <smmintrin.h> // SSE 4.1

float find_largest_element_in_matrix_ref(const float* m, int dims, int *maxIndex)
{
float maxVal = m[0];
int i;

*maxIndex = 0;

for (i = 1; i < dims * dims; ++i)
{
if (m[i] > maxVal)
{
maxVal = m[i];
*maxIndex = i;
}
}
return maxVal;
}

float find_largest_element_in_matrix_SSE(const float* m, int dims, int *maxIndex)
{
float maxVal = m[0];
float aMaxVal[4];
int32_t aMaxIndex[4];
int i;

*maxIndex = 0;

const __m128i vIndexInc = _mm_set1_epi32(4);
__m128i vMaxIndex = _mm_setr_epi32(0, 1, 2, 3);
__m128i vIndex = vMaxIndex;
__m128 vMaxVal = _mm_loadu_ps(m);

for (i = 4; i < dims * dims; i += 4)
{
__m128 v = _mm_loadu_ps(&m[i]);
__m128 vcmp = _mm_cmpgt_ps(v, vMaxVal);
vIndex = _mm_add_epi32(vIndex, vIndexInc);
vMaxVal = _mm_max_ps(vMaxVal, v);
vMaxIndex = _mm_blendv_epi8(vMaxIndex, vIndex, _mm_castps_si128(vcmp));
}
_mm_storeu_ps(aMaxVal, vMaxVal);
_mm_storeu_si128((__m128i *)aMaxIndex, vMaxIndex);
maxVal = aMaxVal[0];
*maxIndex = aMaxIndex[0];
for (i = 1; i < 4; ++i)
{
if (aMaxVal[i] > maxVal)
{
maxVal = aMaxVal[i];
*maxIndex = aMaxIndex[i];
}
}
return maxVal;
}

int main()
{
const int dims = 1024;
float m[dims * dims];
float maxVal_ref, maxVal_SSE;
int maxIndex_ref = -1, maxIndex_SSE = -1;
int i;

srand(time(NULL));

for (i = 0; i < dims * dims; ++i)
{
m[i] = (float)rand() / RAND_MAX;
}

maxVal_ref = find_largest_element_in_matrix_ref(m, dims, &maxIndex_ref);
maxVal_SSE = find_largest_element_in_matrix_SSE(m, dims, &maxIndex_SSE);

if (maxVal_ref == maxVal_SSE && maxIndex_ref == maxIndex_SSE)
{
printf("PASS: maxVal = %f, maxIndex = %d\n",
maxVal_ref, maxIndex_ref);
}
else
{
printf("FAIL: maxVal_ref = %f, maxVal_SSE = %f, maxIndex_ref = %d, maxIndex_SSE = %d\n",
maxVal_ref, maxVal_SSE, maxIndex_ref, maxIndex_SSE);
}
return 0;
}

编译运行:

$ gcc -Wall -msse4 Yakovenko.c && ./a.out 
PASS: maxVal = 0.999999, maxIndex = 120409

显然,如果需要,您可以获得行和列索引:

int rowIndex = maxIndex / dims;
int colIndex = maxIndex % dims;

从这里开始,编写 AVX2 实现应该相当简单。

关于c++ - 使用 SSE 和 AVX 查找矩阵中的最大元素及其列和行索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33844471/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com