标签: simd

C++:是否有理由为类型设置alignof > sizeof

如这个问题所示,对齐方式可能大于类型的大小,只是不能创建它的数组。但是,您可以创建一个 char[alignof(T)] 和reinterpret_cast 数组以在其中插入元素。

所以问题就变成了,在某些情况下,alignof(T) > sizeof(T)会很有用吗?我唯一能想到的就是与 SIMD 边界对齐。

c++ types simd sizeof alignment

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

C simd _m128 晶圆厂

如何为 __m128 向量制作 fabs() ?

我是否必须使用符号位将原始向量乘以 1.0f/-1.0f ?

没有找到任何指令集来做到这一点。

我不需要 __m256 或 512。我正在搜索 __m128 数据类型

c sse simd absolute-value

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

在 0..1 之间将 u64 转换为 f64

我需要一个非常快速的伪随机数生成器来用于我一直在进行的项目。到目前为止,我已经实现了 xorshift 算法,并且可以生成伪随机 u64。但是,我需要将这些 u64 转换为 0 到 1 范围内的浮点值。

我主要使用这个这个作为参考。

由于某种原因,我无法接近我想要的行为;这让我感到困惑,因为我使用了与此处完全相同的方法。尽管我看到实现没有任何差异,但我得到了不同的结果。

    let seeds: [u64; 64] = core::array::from_fn(|i| i as u64);

    let bitshift12 = u64x64::splat(12);
    let bitshift25 = u64x64::splat(25);
    let bitshift27 = u64x64::splat(27);
    
    let bitshift52 = u64x64::splat(52);
    
    let mut random_states = Simd::from(seeds);
    
    random_states ^= random_states >> bitshift12;
    random_states ^= random_states << bitshift25;
    random_states ^= random_states >> bitshift27;
    
    random_states = random_states | ((u64x64::splat(1023) + u64x64::splat(0)) << bitshift52);
    
    let mut generated = Simd::<f64, 64>::from_bits(random_states);
    
    println!("{:?}", generated); …
Run Code Online (Sandbox Code Playgroud)

random floating-point simd rust

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

如何优化测试以检查 std::array&lt;float, 4&gt; 是否包含超出范围的值?

我有一个 4D 向量:std::array<float, 4>

我想检查它的所有组件是否都在值范围内:0.0f <= X && X < 256.0f

如何检查向量分量是否超出此范围?我所需要的只是一个布尔值来知道整个向量是否通过测试。

我第一次尝试解决这个问题是下面的代码:

bool Check_If_Outside_2(std::array<float, 4> vec)
{
    bool outside = false;

    for (int i = 0; i < 4; i++)
        if (vec[i] < VType(0) || vec[i] >= VType(256))
            outside = true;

    return outside;
}
Run Code Online (Sandbox Code Playgroud)

这导致了这个汇编器输出:

Check_If_Outside_2(std::array<float, 4ul>):  # @Check_If_Outside_2(std::array<float, 4ul>)
        vxorps  xmm2, xmm2, xmm2
        vucomiss        xmm0, xmm2
        setb    al
        vmovss  xmm3, dword ptr [rip + .LCPI7_0] # xmm3 = mem[0],zero,zero,zero
        vucomiss        xmm0, xmm3
        setae   cl
        or      cl, …
Run Code Online (Sandbox Code Playgroud)

c++ optimization assembly simd intrinsics

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

Intrinsics中Neon的校验和代码实现

我正在尝试使用内在函数为NEON实现校验和计算代码(2的补码加法).目前的校验和计算正在ARM上进行.

我的实现从存储器一次取128位到NEON寄存器并进行SIMD(加法),结果从128位数字折叠成16位数.

一切看起来都很好,但我的NEON实现消耗的时间比ARM版本多.

ARM版本需要:0.860000 s NEON版本需要:1.260000 s

注意:

  1. 使用"time.h"中的实用程序进行概述
  2. 校验和函数从示例应用程序调用10,000次,并在完成所有函数运行后计算时间

其他详情:

  1. 使用GNU工具链(arm-none-linux-gnueabi-gcc)来编译内在代码而不是arm工具链.
  2. Linux平台.
  3. C内在代码.

问题:

  1. 为什么NEON版本比ARM版本花费更多时间?(虽然我已经注意使用批次中具有最小循环的内在因素)

  2. 如何实现我想要实现的目标?(与NEON的效率)

  3. 有人可以指向我或分享一些使用ARM-NEON的互操作的示例实现(伪代码/算法/代码,而不是理论实现论文或会谈)吗?

任何帮助将非常感激.

这是我的代码:

uint16_t do_csum(const unsigned char * buff, int len)
{
int odd, count, i;

uint32x4_t result = veorq_u32( result, result), sum = veorq_u32( sum, sum); 
uint16x4_t data, data_hi, data_low, data8;
uint16x8_t dataq;
uint16_t result16, disp[20] = {0,0,0,0,0,0,0,0,0,0};

if (len <= 0)
    goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
    uint8x8_t data1 = veor_u8( data1, data1); …
Run Code Online (Sandbox Code Playgroud)

embedded arm simd neon cortex-a8

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

使用SSE内在函数时结果不正确

我正在尝试使用SSE内在函数的8个浮点数组的每个元素,只是为了学习如何使用它们.但是,当我尝试这样写时:

alignas(16) float Numbers[8] = 
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};    

__m128 Group1 = _mm_load_ps(Numbers);
__m128 Group2 = _mm_load_ps(Numbers + 4*sizeof(float));
__m128 Zero = _mm_setzero_ps();

__m128 Sum1 = _mm_add_ps(Group1, Group2);     // Sum1 = Group1 + Group2
__m128 Sum2 = _mm_hadd_ps(Sum1, Zero);        // Sum2[31:0] = Sum1[31:0] + Sum1[63:32]
                                              // Sum2[63:32] = Sum1[95:64] + Sum1[127:96]
__m128 Sum3 = _mm_hadd_ps(Sum2, Zero);        // Sum3[31:0] = Sum2[31:0] + Sum2[63:32]

float Result;
_mm_store_ss(&Result, Sum3);
Run Code Online (Sandbox Code Playgroud)

Result当它应该是28时,它出现了6.我一直在指这些内在函数的参考,但我无法找出我的逻辑在这里出了什么问题.有什么建议?

c++ x86 sse simd intrinsics

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

无符号长整型数组的sse和

基于SSE浮点向量的减少,我试图对无符号长数组求和,但是很不幸,没有成功。

uint64_t vsum_uint64 (uint64_t *a, int n)
{
    uint64_t sum;    // lets say sum fits
    __m128 vsum = _mm_set1_ps(0);

    for (int i = 0; i < n; i += 2) {    // 2 unit64 in single __m128
        __m128 v = _mm_loadl_epi64(&a[i]);
        vsum = _mm_add_epi64(vsum, v);
    }

    _mm_store_ss(&sum, vsum);
    uint64_t *p = &vsum;
    sum+=*(p+1);

    // vsum = _mm_hadd_ps(vsum, vsum);
    // vsum = _mm_hadd_ps(vsum, vsum);
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

这应该是正确的,但是gcc仍然无法编译它。我搜索了答案,但没有找到答案。

这就是gcc所说的:

main.cpp: In function ‘uint64_t vsum_uint64(const uint64_t*, int)’:
main.cpp:73:35: …
Run Code Online (Sandbox Code Playgroud)

c++ sse sum simd uint64

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

SIMD在超标量无序CPU上有什么好处?

我一直在阅读最近推出的AVX-512指令,我觉得有一个我不理解的基本概念.SIMD对已执行乱序执行的超标量CPU有什么好处?

请考虑以下伪汇编代码.使用SIMD:

load 16 floats to register simd-a
load 16 floats to register simd-b
multiply register simd-a by simd-b as 16 floats to register c
store the results to memory
Run Code Online (Sandbox Code Playgroud)

这没有SIMD:

load a float to register a
load a float to register b
multiply register a and register b as floats to c
store register c to memory

load a float to register a (contiguous to prior load to a)
load a float to register b (contiguous to prior load …
Run Code Online (Sandbox Code Playgroud)

simd

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

是否可以使用SIMD指令进行替换?

我有int的向量,我需要找到替换一些具有特定值的元素.两者都是一样的.
例如:为所有元素替换4到8.

我在c ++中尝试循环内存访问.但它对我来说仍然很慢.

更新:
我正在使用OpenCV Mat对象x86:

for (int i = 0; i < labels.rows; ++i) {
    for (int j = 0; j < labels.cols; ++j) {
        int& label = labels.at<int>(i, j);
        if (label == oldValue) {
            label = newValue;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mat.at() 函数只是在释放模式下通过指针返回值

template<typename _Tp> inline
_Tp& Mat::at(int i0, int i1)
{
    CV_DbgAssert(dims <= 2);
    CV_DbgAssert(data);
    CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
    CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
    CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm replace simd

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

如何使用SSE2处理exp()?

我正在制作一个基本上利用SSE2优化此代码的代码:

double *pA = a;
double *pB = b[voiceIndex];
double *pC = c[voiceIndex];

for (int sampleIndex = 0; sampleIndex < blockSize; sampleIndex++) {
    pC[sampleIndex] = exp((mMin + std::clamp(pA[sampleIndex] + pB[sampleIndex], 0.0, 1.0) * mRange) * ln2per12);
}
Run Code Online (Sandbox Code Playgroud)

在这:

double *pA = a;
double *pB = b[voiceIndex];
double *pC = c[voiceIndex];

// SSE2
__m128d bound_lower = _mm_set1_pd(0.0);
__m128d bound_upper = _mm_set1_pd(1.0);
__m128d rangeLn2per12 = _mm_set1_pd(mRange * ln2per12);
__m128d minLn2per12 = _mm_set1_pd(mMin * ln2per12);

__m128d loaded_a = _mm_load_pd(pA);
__m128d loaded_b = _mm_load_pd(pB); …
Run Code Online (Sandbox Code Playgroud)

c++ simd intrinsics sse2 exp

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