标签: simd

数据对齐以实现矢量化/高效的缓存访问

本书说如下:

对于 Knights Landing,当数据起始地址位于 64 字节边界时,内存移动是最佳的。

Q1. 有没有办法在 C++ 代码中动态查询处理器,以了解n当前运行应用程序的处理器的最佳字节边界是什么?这样,代码就可以移植了。

书中进一步指出:

作为程序员,我们最终有两项工作:(1)对齐我们的数据;(2)确保编译器知道它是对齐的。

(假设对于下面的问题,我们知道处理器的最佳数据是从 64 字节边界开始。)

这个“数据”到底是什么?

假设我有一堂课:

class Class1_{
    private: 
    int a;//4 bytes
    double b;//8 bytes
    std::vector<int> potentially_longish_vector_int;
    std::vector<double> potentially_longish_vector_double;
    double * potentially_longish_heap_array_double;
    public:
    //--stuff---//
    double * return_heap_array_address() {return potentially_longish_heap_array_double;}
}
Run Code Online (Sandbox Code Playgroud)

假设我还有原型化的函数:

void func1(Class1_& obj_class1);

void func2(double* array);
Run Code Online (Sandbox Code Playgroud)

也就是说,通过引用func1接收一个对象,并调用为Class1_func2func2(obj_class1.return_heap_array_address());

为了与数据应该适当边界对齐的建议保持一致,obj_class1它本身应该是 64 字节边界对齐以实现 的有效运行func1()吗?应该potentially_longish_heap_array_double对齐 64 字节边界才能有效运行吗func2()

对于作为 STL 容器的类的其他数据成员的对齐,此处的线程建议如何完成所需的对齐。

Q2。那么,对象本身以及其中的所有数据成员是否需要适当对齐?

c++ simd vectorization memory-alignment compiler-optimization

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

使用 SIMD 的 C# 中的 2x2 矩阵向量积

我正在做一些事情,我想每秒多次将相同的 2x2short值矩阵与不同的二维值向量相乘,在这种情况下性能很重要。short现在,我只是以幼稚的方式进行并写出矩阵乘法。我查阅了C#的SIMD功能,发现没有办法制作这种类型的2x2矩阵。Vector<T>所以我尝试使用的结构来做到这一点System.Numerics.Vectors。不过,构造函数预计至少有 4 个元素进入向量。我可以解决它并使其与 4 维向量一起工作,但我想知道是否有一种方法可以更轻松地完成我想做的事情:将 2x2 矩阵与 2 维向量相乘成一个新的 2 维向量与SIMD。

c# simd

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

使用 SIMD 内在函数加载或洗牌一对浮点数以实现双精度?

我编写了一些用于处理单精度浮点计算 SIMD 内在函数的优化。

有时,双精度指令比任何单精度指令pd更容易满足我的要求。ps

示例1:

我有指针float prt * ,它指向浮点数块: f0 f1 f2 f3 等。

我想用 [ f0, f1, f0, f1, f0, f1, f0, f1 ] 加载 __m256 值。我没有找到__m256数据类型的 64 位广播。我可以_mm256_broadcast_sd在花车上使用吗?

float* ptr = ...; // pointer to some memory chunk aligned to 4 bytes
__m256 vat = _mm256_castpd_ps( _mm256_broadcast_sd( ( double* )ptr ) );
Run Code Online (Sandbox Code Playgroud)

示例2:

我有 __m256 值 [f0, f1, f2, f3, f4, f5, f6, f7]。我可以使用像 _mm256_srl_epi32 这样的移位指令,它以 __m256i 值作为参数来使用我的 __m256 值进行操作吗? …

c sse simd intrinsics avx

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

NEON 代码在 armeabi-v7a 上比标准 C 代码更快,但在 arm64-v8a 上更慢

我正在尝试hello neon提供的示例,android/ndk-samples并在两台设备上测试了 fir 过滤器演示,一台设备支持ABI armeabi-v7a,另一台设备支持arm64-v8aABI。

默认情况下,JNI 代码会失败arm64-v8a,但这可以通过一些调整来解决。现在,当我最终在两个设备上运行比较代码(具有不同规格)时,我得到以下结果

armeabi-v7a设备 - 四核,32 位

C Version:      182.47 ms
Neon Version:   69.782 ms (2.62x faster)
Run Code Online (Sandbox Code Playgroud)

arm64-v8a设备 - 八核,64 位

C Version:      10.189 ms
Neon Version:   19.4836 ms (0.52295x faster)
Run Code Online (Sandbox Code Playgroud)

问题

为什么这个霓虹灯版本的速度会变慢arm64-v8a

(我对 NEON 和 SIMD 相当陌生)

链接到内部代码 - cpp/helloneon-intrinsics.c

c optimization performance simd neon

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

vrecpeq_f32 内在函数的参考实现?

vrecpeq_f32ARM NEON Intrinsic。

官方解释vrecpeq_f32https://developer.arm.com/architectures/instruction-sets/intrinsics/#f :@navigationhierarchiessimdisa=[Neon]&q=vrecpeq_f32 。

浮点倒数估计。该指令查找源 SIMD&FP 寄存器中每个向量元素的近似倒数估计,将结果放入向量中,并将该向量写入目标 SIMD&FP 寄存器。

然而,它对我来说仍然不准确。只是想知道我们是否可以用 C/C++ 编写一个参考实现来保持与 完全相同的结果vrecpeq_f32

我尝试打电话 vrecpeq_f32并得到结果:

float32x4_t v1 = {1, 2, 3, 4};
float32x4_t v_out = vrecpeq_f32(v1);//0.99805, 0.49902, 0.33301, 0.24951
Run Code Online (Sandbox Code Playgroud)

很好奇为什么 1 的倒数是 0.99805 而不是 1.0。

PS 我对如何使用 NEON 内在函数和一些技巧来获得更好的精度倒数结果不感兴趣,例如一次或多次牛顿-拉夫森迭代。

c++ simd intrinsics neon

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

内在向量与朴素向量约简结果的差异

我一直在比较 Intrinsics 向量缩减、朴素向量缩减和使用 openmp 编译指示的向量缩减的运行时间。然而,我发现这些场景的结果是不同的。代码如下 - (内在向量归约取自 - Fastest way to dohorizo​​ntal SSE vector sum(或其他归约)

#include <iostream>
#include <chrono>
#include <vector>
#include <numeric>
#include <algorithm>
#include <immintrin.h>


inline float hsum_ps_sse3(__m128 v) {
    __m128 shuf = _mm_movehdup_ps(v);        // broadcast elements 3,1 to 2,0
    __m128 sums = _mm_add_ps(v, shuf);
    shuf        = _mm_movehl_ps(shuf, sums); // high half -> low half
    sums        = _mm_add_ss(sums, shuf);
    return        _mm_cvtss_f32(sums);
}


float hsum256_ps_avx(__m256 v) {
    __m128 vlow  = _mm256_castps256_ps128(v);
    __m128 vhigh = _mm256_extractf128_ps(v, 1); // high …
Run Code Online (Sandbox Code Playgroud)

c++ vector simd intrinsics ieee-754

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

AVX 将 __m256i 打包的 32 位整数除以二(无 AVX2)

__m256i我正在寻找使用 AVX 将压缩的 32 位整数除以二(也称为右移一位)的最快方法。我无法访问 AVX2。据我所知,我的选择是:

  1. 下拉至SSE2
  2. 类似于有符号 32 位元素的 AVX __m256i 整数除法

如果我需要使用 SSE2,我会欣赏最好的 SSE2 实现。如果是 2),我想知道要使用的内在函数,以及是否有更优化的实现来专门除以 2。谢谢!

c++ sse simd avx sse2

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

有没有更好的方法来检测 16 字节标志数组中设置的位?

    ALIGNTO(16) uint8_t noise_frame_flags[16] = { 0 };

    // Code detects noise and sets noise_frame_flags omitted

    __m128i xmm0            = _mm_load_si128((__m128i*)noise_frame_flags);
    bool    isNoiseToCancel = _mm_extract_epi64(xmm0, 0) | _mm_extract_epi64(xmm0, 1);

    if (isNoiseToCancel)
        cancelNoises(audiobuffer, nAudioChannels, audio_samples, noise_frame_flags);
Run Code Online (Sandbox Code Playgroud)

这是我在 Linux 上的 AV Capture 工具的代码片段。这里的noise_frame_flags是16通道音频的标志数组。对于每个通道,相应的字节可以是 0 或 1。1 表示该通道有一些噪声需要消除。例如,如果noise_frame_flags[0] == 1,则意味着设置了第一个通道噪声标志(通过省略的代码)。

即使设置了一个“标志”,我也需要调用cancelNoises. 这段代码在这方面似乎工作得很好。正如您所看到的,我曾经_mm_load_si128加载正确对齐的整个标志数组,然后加载两个_mm_extract_epi64来提取“标志”。我的问题是有更好的方法来做到这一点(也许使用流行计数)?

注意:ALIGNTO(16)是一个宏扩展以纠正 GCC 等效项,但外观更好。

c++ sse x86-64 simd micro-optimization

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

对于 gcc 编译器,当您在没有任何标志的情况下与 -O2 进行编译时,gcc 的目标是什么 x86-64 指令集?

对于 x86-64,有许多指令集可以加速代码执行。以下是 gcc wiki https://gcc.gnu.org/wiki/FunctionMultiVersioning的列表:

  • 多媒体MX
  • 上证所
  • 上证2
  • SSE3
  • SSSE3
  • SSE4.1
  • SSE4.2
  • POPCNT
  • AVX
  • AVX2

对于 gcc 编译器,当您在没有任何标志的情况下编译时,gcc 的目标是什么 x86-64 指令集-O2

为了简单起见,我们只说问题是关于 gcc 版本 12(最新的主要版本)。但我想知道我需要做什么 gcc 命令开关/选项,以便我可以看到我的 gcc 版本的功能。

我认为 gcc 选择了“可移植”的东西,所以这可能意味着速度很慢。但这只是我的假设......我想知道这是否意味着像SSE4.2或没有?

gcc x86-64 simd compiler-optimization

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

访问mm1寄存器部件

是否可以访问mmx寄存器中的单个字节,如数组?我有这个代码:

movq mm1,vector1
movq mm2,vector2
psubw mm1,mm2
Run Code Online (Sandbox Code Playgroud)

我想把mm1 [1],mm1 [2],mm1 [3] ....放到c ++变量中,比如:

int a,b=0;
mov a,mm1[1]
mov b,mm1[2]
Run Code Online (Sandbox Code Playgroud)

谢谢.

c++ x86 sse simd mmx

0
推荐指数
2
解决办法
335
查看次数