首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从浮点数加载到__m256 *但是在内存中反向读取,而不是向前读取?

如何从浮点数加载到__m256 *但是在内存中反向读取,而不是向前读取?
EN

Stack Overflow用户
提问于 2021-12-07 16:28:36
回答 2查看 750关注 0票数 1

我有一组浮点数,我想以相反的顺序访问。在我的非矢量化代码中,这很容易。

以下是我所拥有的数据的简化版本。

代码语言:javascript
复制
float A[8] = {a, b, c, d, e, f, g, h};
float B[8] = {s, t, u, v, w, x, y, z};

这是我想做的手术。

代码语言:javascript
复制
float C[8] = {a*z, b*y, c*x, d*w, e*v, f*u, g*t, h*s};

我希望能够执行某种load_ps操作,这样的操作可以给我这样的结果:

代码语言:javascript
复制
__m256 A_Loaded         = _mm256_load_ps(&A[0]);
                        = {a, b, c, d, e, f, g, h};

__m256 B_LoadedReversed = _mm256_loadr_ps(&B[7]);
                        = {z, y, x, w, v, u, t, s};

__m256 Output = _mm256_mul_ps(A_Loaded, B_LoadedReversed);
              = {a*z, b*y, c*x, d*w, e*v, f*u, g*t, h*s};

我所拥有的数据源之一是一个查找表,因此,如果推到紧要关头,它可能会被逆转,但更倾向于避免这种情况,因为那样会编译程序的其他区域。

目前,我已经找到了一个使用_mm256_set_ps()并手动指向所需数据的拙劣解决方案,但这并不像我所希望的那样具有良好的性能。

我知道有一个“反向”的_mm256_set_ps() (_mm256_setr_ps()),但似乎没有我需要的_mm256_loadr_ps()

任何关于这个问题的想法和想法都将不胜感激!提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-12-07 16:48:08

您可以使用__m256_mm_256_permute2f128_ps,分两步逆转_mm256_permute_ps内部的顺序。

  • _mm256_permute_ps允许你在每条“车道”内保持不变,即高和低128位块。
  • _mm_256_permute2f128_ps允许你在车道上设置128位块.

就像这样:

代码语言:javascript
复制
__m256 b = _mm256_loadr_ps(&B[0]);
b = _mm256_permute_ps(b, _MM_SHUFFLE(3, 2, 1, 0));
b = _mm256_permute2f128_ps(b, b, 1);

这些说明记录在英特尔的本质指南:https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html中。

setr_ps是如何工作的?

setr_ps()是如何逆转的呢?它只是颠倒了论点。这是我从GCC安装中提取的版本:

代码语言:javascript
复制
extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm256_setr_ps (float __A, float __B, float __C, float __D,
                float __E, float __F, float __G, float __H)
{
  return _mm256_set_ps (__H, __G, __F, __E, __D, __C, __B, __A);
}

您可以看到,setr_ps()并不对应于任何底层处理器功能,它只是重新排序参数。

票数 1
EN

Stack Overflow用户

发布于 2021-12-07 16:37:10

你不能用一个负载来表达它--所有的负载都是“向前”的。

你得用洗牌手术。名字中有“永久”或"shuf“的东西。如果_mm256_permutevar8x32_ps是可用的,那么AVX2可能对您的情况是一个很好的选择。它可以在一次洗牌指令中完成所有的工作,尽管它确实需要加载一个洗牌控制向量。如果只有AVX1可用,Dietrich的回答提出了一种使用两种AVX1洗牌的方法。

类似这样的内容(如果我没有反转索引):

代码语言:javascript
复制
// AVX2
__m256 B_LoadedReversed = _mm256_permutevar8x32_ps(
                              _mm256_load_ps(&B[0]),  // load B[0..7]
                              _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7));

这些函数的参数之一是指数向量,或者对于其他洗牌,如在车道的_mm256_permute_ps,它是一个8位的即时值(imm8)。

参数的每个元素都是源向量元素在目标向量中的位置。对于imm8,有2位位置。

有些洗牌函数对给定向量的子向量执行多次洗牌,但对这一次不执行。

许多AVX+洗牌不跨车道( 128位组),但这次确实如此。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70263686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档