Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 带有_m256的并集和两个_m128的数组_C_Performance_Sse_Vectorization_Avx - Fatal编程技术网

C 带有_m256的并集和两个_m128的数组

C 带有_m256的并集和两个_m128的数组,c,performance,sse,vectorization,avx,C,Performance,Sse,Vectorization,Avx,我能有这样的工会吗 union eight_floats_t { __m256 a; __m128 b[2]; }; eight_floats_t eight_floats; 要即时访问256位寄存器的两个128位部分 编辑:我想了解这种方法对性能的影响。是的,你可以。你试过了吗 请注意,C标准规定,访问非最近写入的工会成员属于未指定行为——具体而言,如果您先写入一个成员,然后读取另一个成员,则另一个成员具有未指定的值(C99§6.2.6.1/7)。但是,它是一

我能有这样的工会吗

  union eight_floats_t
  {
    __m256 a;
    __m128 b[2];
  };
  eight_floats_t eight_floats;
要即时访问256位寄存器的两个128位部分


编辑:我想了解这种方法对性能的影响。

是的,你可以。你试过了吗


请注意,C标准规定,访问非最近写入的工会成员属于未指定行为——具体而言,如果您先写入一个成员,然后读取另一个成员,则另一个成员具有未指定的值(C99§6.2.6.1/7)。但是,它是一种非常常见的习惯用法,并且受到所有主要编译器的良好支持。实际上,以任何顺序向工会任何成员进行阅读和写作都是可以接受的做法()。

你当然可以这样做。C语言和C++语言允许你这么做。它很可能会做你想让它做的事

但是,使用AVX意味着您关心性能。因此,了解这是SSE程序员陷入的最常见(性能)陷阱之一可能很有用。(许多人没有注意到)

问题1:

当前的编译器使用内存位置实现这种联合。所以这是第一个问题,每次从不同的字段访问union时,它都会将数据强制存储在内存中并将其读回。这是一个慢下来

以下是MSVC2010生成的内容(经过优化):

你可以看到它正在被刷新到内存中

问题2:

第二次减速更糟糕。当您将某个内容写入内存,并立即以不同的字大小访问它时,您可能会触发存储以加载暂停。(通常在>10个周期的顺序上)

这是因为当前处理器上的负载存储队列通常不是为处理这种(异常)情况而设计的。因此,他们通过简单地将队列刷新到内存中来处理它


访问AVX数据类型下半部分和上半部分的“正确”方法是使用:

  • \u mm256\u extractf128\u ps()
  • \u mm256\u insertf128\u ps()
  • \u mm256\u castps256\u ps128()
还有家人。对于其他数据类型也是如此


也就是说,编译器可能足够聪明,能够识别您正在做什么,并使用这些指令。(至少MSVC2010没有。)

你当然可以。但是如果编译器不知道如何优化它,您将支付性能损失。您确定这是UB吗?gcc手册实际上推荐了这种避免类型双关点的做法,我也尝试过,但我想了解它对性能的影响,就像神秘的假设一样。谢谢。@hirschhornsalz:我仔细看了一下,你说得对,那不是UB。C99§6.2.6.1/7说,“当一个值存储在联合类型的对象的成员中时,与该成员不对应但与其他成员相对应的对象表示字节采用未指定的值。”@AdamRosenfield I也仔细查看了一下,实际上似乎C99中没有UB,而C++11中没有UB,请看,值得注意的是,这实际上不应该占用当前网络上的商店货运摊位;32B存储区被破解为两个16B存储区µop,每一个都转发给相应的load op,不会对相应的load op造成危害。但是,这不会影响您的一般“请勿执行此操作”消息。很高兴知道这一点。我不知道Intels也是这样。尽管我认为在未来,32字节的存储可能会变成“本地的”。@Mystical:即使它们是本地的,我希望转发继续工作(事实上,英特尔在所有没有病态失调的情况下都投入了大量精力来实现转发——例如,最近的一次尝试将16B存储转发到任何不跨越8B边界的较小负载,以及明显的16B负载——顺便说一句,这都记录在他们的优化手册中)@Mysticial大约4年前你说“当前编译器…”。你的答案仍然正确吗?@16num自4年前以来,这种行为一点也没有改变。它仍然会在内存中双向运行,并会导致存储加载暂停。因此,不,编译器在这方面没有进步。
eight_floats a;
a.a = vecA[0];

__m128 fvecA = a.b[0];
__m128 fvecB = a.b[1];
fvecA = _mm_add_ps(fvecA,fvecB);
vmovaps YMMWORD PTR a$[rbp], ymm0
movaps  xmm1, XMMWORD PTR a$[rbp+16]
addps   xmm1, XMMWORD PTR a$[rbp]
movaps  XMMWORD PTR fvecA$[rbp], xmm1
movss   xmm1, DWORD PTR fvecA$[rbp]