标签: avx2

对齐AVX-256内存存储是否值得打扰?

根据英特尔®64和IA-32架构优化参考手册 B.4节("英特尔®微体系架构代码名称Sandy Bridge的性能调整技术"),B.4.5.2小节("协助"):

跨越两页的32字节AVX存储指令需要一个大约150个周期的辅助.

我正在使用YMM寄存器来复制小型固定大小的内存块,从32到128个字节,并且这些块在堆管理器中以16个字节对齐.该堆管理器之前使用过XMM寄存器movdqa,我想将其"升级"为YMM,而不将对齐从16字节更改为32字节.所以我正在使用vmovdqu ymm0, ymmword ptr [rcx],vmovdqu ymmword ptr [rdx], ymm0等等......

如果我正确理解了英特尔文档的页面大小,如果我在4K页面边界上进行32字节存储,那么我将获得150个周期的惩罚.

但由于这些块已经对齐了16个字节,因此我点击跨页面存储的可能性是16/4096 = 1/256.如果我们在统计上推断出,在每个32字节的存储上,我在Sandy Bridge上得到1/255*150(= 0.5859375)个周期惩罚.

这不是那么多,并且由于将对齐从16字节更改为32字节,因此检查对齐或内存浪费肯定比分支更便宜.

我有以下问题:

  1. 我的计算是否正确?

  2. 对齐AVX-256内存存储器是否值得为小型固定大小的内存复制例程(32-128字节)而烦恼,因为达到惩罚的可能性如此之低?

  3. 是否存在比Sandy Bridge更高的未对齐32字节存储损失的处理器 - 例如,AMD或其他英特尔微体系结构?

memory assembly x86-64 avx avx2

15
推荐指数
1
解决办法
1082
查看次数

AVX2:计算 512 个浮点数组的点积

我先说我是 SIMD 内在函数的完全初学者。

本质上,我有一个支持 AVX2 内在 ( Intel(R) Core(TM) i5-7500T CPU @ 2.70GHz)的 CPU 。我想知道计算两个std::vector<float>size的点积的最快方法512

我在网上做了一些挖掘,发现了这个这个这个堆栈溢出问题建议使用以下函数__m256 _mm256_dp_ps(__m256 m1, __m256 m2, const int mask);,但是,这些都表明了执行点积的不同方法我不确定什么是正确的(和最快的)方法它。

特别是,我正在寻找对大小为 512 的向量执行点积的最快方法(因为我知道向量大小会影响实现)。

感谢您的帮助

编辑 1:我也对-mavx2gcc 标志有点困惑。如果我使用这些 AVX2 函数,我编译时是否需要添加标志?另外,-OFast如果我编写了一个天真的点积实现,gcc 是否能够为我做这些优化(比如我使用gcc 标志)?

编辑 2 如果有人有时间和精力,如果您能编写完整的实现,我将不胜感激。我相信其他初学者也会重视这些信息。

c++ simd dot-product avx2 fma

15
推荐指数
1
解决办法
3210
查看次数

如何在256位AVX向量中找到水平最大值

我有一个__m256d向量,包含四个64位浮点值.
我需要找到向量元素的水平最大值,并将结果存储在双精度标量值中;

我的尝试最终都使用了很多矢量元素的改组,使得代码不是很优雅也没有效率.此外,我发现不可能只留在AVX域.在某些时候,我不得不使用SSE 128位指令来提取最终的64位值.但是,我想在最后的声明中被证明是错误的.

因此理想的解决方案将:
1)仅使用AVX指令.
2)最小化指令数量.(我希望不超过3-4条说明)

话虽如此,任何优雅/高效的解决方案都将被接受,即使它不符合上述指导原则.

谢谢你的帮助.

-Luigi

x86 simd vector-processing avx avx2

14
推荐指数
2
解决办法
6709
查看次数

AVX中的分散内在函数

我在英特尔Intrinsic Guide v2.7中找不到它们.你知道AVX或AVX2指令集是否支持它们吗?

intrinsics avx avx2

14
推荐指数
2
解决办法
4814
查看次数

使用AVX/AVX2转置8x8浮点数

通过制作四个4x4矩阵并转置每个矩阵,可以实现8x8矩阵的转置.这不是我想要的.

在另一个问题中,一个答案提供了一个解决方案,只需要24个8x8矩阵指令.但是,这不适用于花车.

由于AVX2包含256位寄存器,因此每个寄存器适合8个32位整数(浮点数).但问题是:

如何使用AVX/AVX2转换8x8浮点矩阵,尽可能使用最小的指令?

simd avx avx2

14
推荐指数
2
解决办法
6323
查看次数

我可以使用AVX FMA单元进行精确的52位整数乘法吗?

AXV2没有任何整数乘法,其源大于32位.它提供32 x 32 - > 32乘法,以及32 x 32 - > 64乘以1,但没有64位源.

假设我需要一个输入大于32位但小于或等于52位的无符号乘法 - 我可以简单地使用浮点DP乘法或FMA指令,并且当整数输入和输出时输出将是位精确的结果可以用52或更少的比特表示(即,在[0,2 ^ 52-1]范围内)?

如果我想要产品的所有104位更一般的情况怎么样?或整数乘积超过52位的情况(即,产品在位索引中的非零值> 52) - 但我只想要低52位?在后一种情况下,它MUL会给我更高的位并舍去一些低位(也许这就是IFMA帮助的?).

编辑:事实上,根据这个答案,也许它可以做任何高达2 ^ 53的事情- 我忘记了1在尾数之前隐含的领先有效地给了你一点.


1有趣的是,正如Mysticial 在评论中所解释的那样,64位产品PMULDQ操作的延迟是32位PMULLD版本的一半,吞吐量是32位版本的两倍.

floating-point x86 simd avx2 fma

14
推荐指数
1
解决办法
1278
查看次数

使用AVX2收集指令时加载地址计算

查看AVX2内在函数文档,收集了加载指令,例如VPGATHERDD:

__m128i _mm_i32gather_epi32 (int const * base, __m128i index, const int scale);
Run Code Online (Sandbox Code Playgroud)

从文档中我不清楚的是计算的加载地址是 元素地址还是字节地址,即元素的加载地址i:

load_addr = base + index[i] * scale;               // (1) element addressing ?
Run Code Online (Sandbox Code Playgroud)

要么:

load_addr = (char *)base + index[i] * scale;       // (2) byte addressing ?
Run Code Online (Sandbox Code Playgroud)

英特尔文档看起来它可能是(2),但是这没有多大意义,因为聚集的负载的最小元素大小是32位 - 为什么要从未对齐的地址加载(即使用比例<4) )?

x86 sse simd avx2

13
推荐指数
2
解决办法
4146
查看次数

如何清除__m256值的高128位?

如何清除m2的高128位:

__m256i    m2 = _mm256_set1_epi32(2);
__m128i    m1 = _mm_set1_epi32(1);

m2 = _mm256_castsi128_si256(_mm256_castsi256_si128(m2));
m2 = _mm256_castsi128_si256(m1);
Run Code Online (Sandbox Code Playgroud)

不起作用 - 英特尔针对_mm256_castsi128_si256内在函数的文档说"结果向量的高位未定义".同时我可以在装配中轻松完成:

VMOVDQA xmm2, xmm2  //zeros upper ymm2
VMOVDQA xmm2, xmm1
Run Code Online (Sandbox Code Playgroud)

当然我不想用"和"等等_mm256_insertf128_si256().

c x86 simd avx avx2

13
推荐指数
3
解决办法
672
查看次数

什么是最快的步幅-3收集指令序列?

问题:

从内存生成32位元素的stride-3集合的最有效序列是什么?如果内存安排如下:

MEM = R0 G0 B0 R1 G1 B1 R2 G2 B2 R3 G3 B3 ...
Run Code Online (Sandbox Code Playgroud)

我们想获得三个YMM寄存器,其中:

YMM0 = R0 R1 R2 R3 R4 R5 R6 R7
YMM1 = G0 G1 G2 G3 G4 G5 G6 G7
YMM2 = B0 B1 B2 B3 B4 B5 B6 B7
Run Code Online (Sandbox Code Playgroud)

动机和讨论

标量C代码就像

template <typename T>
T Process(const T* Input) {
  T Result = 0;
  for (int i=0; i < 4096; ++i) {
    T R = Input[3*i];
    T G = Input[3*i+1];
    T B …
Run Code Online (Sandbox Code Playgroud)

c++ x86 vectorization avx2

13
推荐指数
1
解决办法
753
查看次数

为什么在调试和发布模式下存储和加载AVX2 256位向量会产生不同的结果?

当我尝试在AVX2 256位向量中存储加载 256位时,我在发布模式下没有收到预期的输出.

use std::arch::x86_64::*;

fn main() {
    let key = [1u64, 2, 3, 4];
    let avxreg = unsafe { _mm256_load_si256(key.as_ptr() as *const __m256i) };
    let mut back_key = [0u64; 4];
    unsafe { _mm256_storeu_si256(back_key.as_mut_ptr() as *mut __m256i, avxreg) };
    println!("back_key: {:?}", back_key);
}
Run Code Online (Sandbox Code Playgroud)

操场

在调试模式下:

back_key: [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

在发布模式下:

back_key: [1, 2, 0, 0]
Run Code Online (Sandbox Code Playgroud)

后半部分没有被加载或存储,我无法弄清楚哪一个.

什么是奇怪的是针对本机CPU工作.在发布模式+RUSTFLAGS="-C target-cpu=native"

back_key: [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

我甚至试图通过强制对齐无法获得Clippy错误(我不确定下面的代码是否被认为更正确).

use std::arch::x86_64::*;

#[repr(align(256))]
#[derive(Debug)]
struct Key([u64; 4]);

fn main() {
    let …
Run Code Online (Sandbox Code Playgroud)

simd compiler-optimization rust avx2

13
推荐指数
1
解决办法
273
查看次数