获得 8 个源 __m256 向量的水平和的 __m256 的最有效方法[重复]

2023-11-29

我知道如何求和__m256获得单个求和值。然而,我有 8 个向量,例如 输入

1: a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
.....,
.....,
8: h[0], h[1], h[2], h[3], h[4], a[5], a[6], a[7]

Output

a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7], 
 ...., 
h[0]+h[1]+h[2]+h[3]+h[4]+h[5]+h[6]+h[7]

我的方法。好奇是否有更好的方法。

            __m256 sumab = _mm256_hadd_ps(accumulator1, accumulator2);
            __m256 sumcd = _mm256_hadd_ps(accumulator3, accumulator4);

            __m256 sumef = _mm256_hadd_ps(accumulator5, accumulator6);
            __m256 sumgh = _mm256_hadd_ps(accumulator7, accumulator8);

            __m256 sumabcd = _mm256_hadd_ps(sumab, sumcd);
            __m256 sumefgh = _mm256_hadd_ps(sumef, sumgh);

            __m128 sumabcd1 = _mm256_extractf128_ps(sumabcd, 0);
            __m128 sumabcd2 = _mm256_extractf128_ps(sumabcd, 1);
            __m128 sumefgh1 = _mm256_extractf128_ps(sumefgh, 0);
            __m128 sumefgh2 = _mm256_extractf128_ps(sumefgh, 1);

            sumabcd1 = _mm_add_ps(sumabcd1, sumabcd2);
            sumefgh1 = _mm_add_ps(sumefgh1, sumefgh2);

 __m256 result =_mm256_insertf128_ps(_mm256_castps128_ps256(sumabcd1), sumefgh1, 1)

Update: 计算 8 个 AVX 单精度浮点向量的 8 个水平和(我认为)是同样的问题,用一个混合替换其中一个 _mm256_permute2f128_ps 来解决。另一个答案是用更多混合代替洗牌微指令。请改用其中之一。


原始答案未能使用任何混合,并且会在洗牌上出现瓶颈

您可以使用 2x_mm256_permute2f128_ps将低车道和高车道对齐以实现垂直vaddps。这不是 2xextractf128 / insertf128。这也变成了两个128bvaddps xmm指令写入单个 256bvaddps ymm.

vperm2f128与单个一样快vextractf128 or vinsertf128在英特尔 CPU 上。不过,在 AMD 上速度很慢(Bulldozer 系列上有 8 m-ops,延迟为 4c)。不过,即使您关心 AMD 的性能,也还不错,需要避免它。 (其中一个排列实际上可以是vinsertf128).


__m256 hsum8(__m256 a, __m256 b, __m256 c, __m256 d,
             __m256 e, __m256 f, __m256 g, __m256 h)
{
    // a = [ A7 A6 A5 A4 | A3 A2 A1 A0 ]
    __m256 sumab = _mm256_hadd_ps(a, b);
    __m256 sumcd = _mm256_hadd_ps(c, d);

    __m256 sumef = _mm256_hadd_ps(e, f);
    __m256 sumgh = _mm256_hadd_ps(g, h);

    __m256 sumabcd = _mm256_hadd_ps(sumab, sumcd);  // [ D7:4 ... A7:4 | D3:0 ... A3:0 ]
    __m256 sumefgh = _mm256_hadd_ps(sumef, sumgh);  // [ H7:4 ... E7:4 | H3:0 ... E3:0 ]

    __m256 sum_hi = _mm256_permute2f128_ps(sumabcd, sumefgh, 0x31);  // [ H7:4 ... E7:4 | D7:4 ... A7:4 ]
    __m256 sum_lo = _mm256_permute2f128_ps(sumabcd, sumefgh, 0x20);  // [ H3:0 ... E3:0 | D3:0 ... A3:0 ]

    __m256 result = _mm256_add_ps(sum_hi, sum_lo);
    return result;
}

This 按您的预期编译。第二permute2f128实际上编译为vinsertf128,因为它仅以与vinsertf128做。 gcc 4.7 及更高版本执行此优化,但只有更新的 clang 版本才会执行此优化 (v3.7)。如果您关心旧的 clang,请在源代码级别执行此操作。

源代码行的节省大于指令的节省,因为_mm256_extractf128_ps(sumabcd, 0);编译为零指令:这只是一个强制转换。任何编译器都不应该发出vextractf128与 imm8 以外的1. (vmovdqa xmm/m128, xmm总是更适合进入低车道)。干得好,英特尔浪费了一个指令字节来保证您无法使用,因为普通的 VEX 前缀没有空间来编码更长的向量。

The two vaddps xmm指令可以并行运行,因此使用单个vaddps ymm主要只是吞吐量(和代码大小)增益,而不是延迟。

我们确实缩短了 3 个周期,从而完全消除了最终的结果vinsertf128, 尽管。


vhaddps是 3 uop,5c 延迟,每 2c 吞吐量 1 个。 (Skylake 上的延迟为 6c)。这三个微指令中的两个在随机端口上运行。我猜它基本上是做 2xshufps生成操作数addps.

如果我们可以效仿haddps(或者至少获得我们可以使用的水平操作)shufps/addps或者其他什么,我们会领先。不幸的是,我不知道如何。一次洗牌只能用来自两个向量的数据产生一个结果,但我们需要垂直输入addps从两个向量中获取数据。

我认为以另一种方式进行水平求和看起来没有希望。通常,哈德不是一个好的选择,因为常见的水平求和用例只关心其输出的一个元素。这里的情况并非如此:每个元素的每个元素hadd实际使用的结果。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

获得 8 个源 __m256 向量的水平和的 __m256 的最有效方法[重复] 的相关文章

  • 将运算符 << 添加到 std::vector

    我想添加operator lt lt to std vector
  • 使用 CMake 时如何导出 Emscripten 中的 C 函数

    In 本教程 https emscripten org docs porting connecting cpp and javascript Interacting with code html interacting with code
  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • 如何在类文件中使用 Url.Action() ?

    如何在 MVC 项目的类文件中使用 Url Action Like namespace 3harf public class myFunction public static void CheckUserAdminPanelPermissi
  • MVC3中设置下拉列表中的所选项目

    我必须为视图中的下拉列表设置所选项目 但它不起作用 View div class editor label Html LabelFor model gt model Gender div div class editor field Htm
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • 传递 constexpr 对象

    我决定给予新的C 14的定义constexpr旋转并充分利用它 我决定编写一个小的编译时字符串解析器 然而 我正在努力保持我的对象constexpr将其传递给函数时 考虑以下代码 include
  • 有些有助于理解“产量”

    在我不断追求少吸的过程中 我试图理解 产量 的说法 但我不断遇到同样的错误 someMethod 的主体不能是迭代器块 因为 System Collections Generic List 不是迭代器接口类型 这是我被卡住的代码 forea
  • RestSharp获取序列化输出

    我正在寻找一种方法来访问 AddBody 调用的序列化结果 我正在使用内置的 RestSharp 序列化器 例子 class Foo public string FooField void SendRecord var f new Foo
  • 在 C# 中,如何根据在 gridview 行中单击的按钮引用特定产品记录

    我有一个显示产品网格视图的页面 该表内有一列 其中有一个名为 详细信息 的超链接 我想这样做 以便如果用户单击该特定产品的详细信息单元格 将打开一个新页面 提供有关该产品的更多信息 我不确定如何确定哪个Product记录链接的详细信息以及我
  • 如何在 C# Designer.cs 代码中使用常量字符串?

    如何在 designer cs 文件中引用常量字符串 一个直接的答案是在我的 cs 文件中创建一个私有字符串变量 然后编辑 Designer cs 文件以使用此变量 而不是对字符串进行硬编码 但设计者不喜欢这样抛出错误 我明白为什么这行不通
  • 不同 C++ 文件中的相同类名

    如果两个 C 文件具有相同名称的类的不同定义 那么当它们被编译和链接时 即使没有警告也会抛出一些东西 例如 a cc class Student public std string foo return A void foo a Stude
  • 如何使用 ASP.NET Core 获取其他用户的声明

    我仍在学习 ASP NET Core 的身份 我正在进行基于声明的令牌授权 大多数示例都是关于 当前 登录用户的 就我而言 我的 RPC 服务正在接收身份数据库中某个用户的用户名和密码 我需要 验证是否存在具有此类凭据的用户 获取该用户的所
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • 如果输入被重定向则执行操作

    我想知道如果我的输入被重定向 我应该如何在 C 程序中执行操作 例如 假设我有已编译的程序 prog 并且我将输入 input txt 重定向到它 我这样做 prog lt input txt 我如何在代码中检测到这一点 一般来说 您无法判
  • 将二变量 std::function 转换为单变量 std::function

    我有一个函数 它获取两个值 x 和 y 并返回结果 std function lt double double double gt mult double x double y return x y 现在我想得到一个常量 y 的单变量函数
  • 如何最好地以编程方式将 `__attribute__ ((unused))` 应用于这些自动生成的对象?

    In my makefile我有以下目标 它将文本 HTML 资源 编译 为unsigned char数组使用xxd i http linuxcommand org man pages xxd1 html 我将结果包装在匿名命名空间和标头保
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • 在 System.Type 上使用条件断点时出错

    这是函数 public void Init System Type Type this Type Type BuildFieldAttributes BuildDataColumns FieldAttributes 我在第一行设置了一个断点
  • 是否允许全局静态标识符以单个 _ 开头?

    换句话说 可能static 文件范围 全局变量恰好以一个下划线开头 而不会产生与 C 实现发生名称冲突的可能性 https www gnu org software libc manual html node Reserved Names

随机推荐