相关疑难解决方法(0)

在x86上做水平浮点矢量和的最快方法

你有一个三(或四)个浮点数的向量.总结它们的最快方法是什么?

SSE(movaps,shuffle,add,movd)总是比x87快吗?SSE4.2中的水平加法说明值得吗?移动到FPU的成本是多少,然后是faddp,faddp?什么是最快的特定指令序列?

"尝试安排事情,这样你可以一次总结四个向量"将不被接受作为答案.:-)

floating-point optimization x86 assembly sse

41
推荐指数
4
解决办法
2万
查看次数

替换默认的STL分配器

我有一个大型(> 250个文件)库的源,它大量使用STL容器和字符串.我需要在有限堆的嵌入式环境中运行它,所以我想确保这个库本身在其堆使用方面受到限制.

显而易见的解决方案是创建一个分配器,但是修改整个代码库以包含分配器模板参数是最后的一项重要工作,如果我想要使用新版本的源,这是不可取的.全局替换new和delete是不可行的,因为这会影响整个图像,而不仅仅是这个库.

我的下一个想法是一个愚蠢的C宏技巧,但这似乎不太可能,虽然我承认不是一个聪明的宏作者.

所以我认为"在编译时是否有编译器或编译指示开关来指定allocator <>类"?但我对任何事情都持开放态度.

我要问的下一个问题是,如果有人能提出解决方案,那么如何在包含该库的文件集中对新/删除做同样的事情.

我正在使用gcc 3.4.4工具链在Cygwin下运行它,目标是VxWorks,如果这引发了任何想法.

c++ stl

21
推荐指数
2
解决办法
6491
查看次数

重叠数组的总和,自动矢量化和限制

Arstechnia最近有一篇文章为什么一些编程语言比其他语言更快.它比较了Fortran和C,并提到了求和数组.在Fortran中,假设数组不重叠,从而允许进一步优化.在C/C++中,指向相同类型的指针可能会重叠,因此通常不能使用此优化.但是,在C/C++中,可以使用restrictor __restrict关键字告诉编译器不要假设指针重叠.所以我开始研究自动矢量化.

以下代码在GCC和MSVC中进行矢量化

void dot_int(int *a, int *b, int *c, int n) {
    for(int i=0; i<n; i++) {
        c[i] = a[i] + b[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用和不使用重叠数组测试了它,它得到了正确的结果.但是,我使用SSE手动向量化循环的方式不能处理重叠数组.

int i=0;    
for(; i<n-3; i+=4) {
    __m128i a4 = _mm_loadu_si128((__m128i*)&a[i]);
    __m128i b4 = _mm_loadu_si128((__m128i*)&b[i]);
    __m128i c4 = _mm_add_epi32(a4,b4);
    _mm_storeu_si128((__m128i*)c, c4);
}
for(; i<n; i++) {
    c[i] = a[i] + b[i];
}
Run Code Online (Sandbox Code Playgroud)

接下来我尝试使用__restrict.我假设由于编译器可以假设数组不重叠,它不会处理重叠数组,但GCC和MSVC仍然可以获得重叠数组的正确结果,即使是__restrict.

void dot_int_restrict(int * __restrict a, int * __restrict b, int * __restrict c, …
Run Code Online (Sandbox Code Playgroud)

c c++ optimization sse auto-vectorization

9
推荐指数
2
解决办法
1050
查看次数

自动矢量化不起作用

我正在尝试将我的代码设置为自动向量化,但它无法正常工作.

int _tmain(int argc, _TCHAR* argv[])
{
    const int N = 4096;
    float x[N];
    float y[N];
    float sum = 0;

    //create random values for x and y 
    for (int i = 0; i < N; i++)
    {
        x[i] = rand() >> 1;
        y[i] = rand() >> 1;
    }

    for (int i = 0; i < N; i++){
        sum += x[i] * y[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

这里没有循环矢量化,但我真的只对第二个循环感兴趣.

我正在使用visual studio express 2013并且正在编译/O2/Qvec-report:2(报告循环是否被矢量化)选项.编译时,我收到以下消息:

--- Analyzing function: main
c:\users\...\documents\visual studio 2013\projects\intrin3\intrin3\intrin3.cpp(28) …
Run Code Online (Sandbox Code Playgroud)

c++ optimization sse simd vectorization

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

展开循环并使用矢量化进行独立求和

对于以下循环,如果我告诉它使用关联数学,例如,GCC将仅对循环进行矢量化-Ofast.

float sumf(float *x)
{
  x = (float*)__builtin_assume_aligned(x, 64);
  float sum = 0;
  for(int i=0; i<2048; i++) sum += x[i];
  return sum;
}
Run Code Online (Sandbox Code Playgroud)

这是装配 -Ofast -mavx

sumf(float*):
    vxorps  %xmm0, %xmm0, %xmm0
    leaq    8192(%rdi), %rax
.L2:
    vaddps  (%rdi), %ymm0, %ymm0
    addq    $32, %rdi
    cmpq    %rdi, %rax
    jne .L2
    vhaddps %ymm0, %ymm0, %ymm0
    vhaddps %ymm0, %ymm0, %ymm1
    vperm2f128  $1, %ymm1, %ymm1, %ymm0
    vaddps  %ymm1, %ymm0, %ymm0
    vzeroupper
    ret
Run Code Online (Sandbox Code Playgroud)

这清楚地表明循环已被矢量化.

但是这个循环也有一个依赖链.为了克服添加的延迟,我需要在x86_64上展开并执行至少三次部分和(不包括Skylake,需要展开八次并使用需要在Haswell和Broadwell上展开10次的FMA指令进行添加) .据我所知,我可以展开循环-funroll-loops.

这是装配-Ofast -mavx -funroll-loops.

sumf(float*):
    vxorps …
Run Code Online (Sandbox Code Playgroud)

c x86 gcc loop-unrolling auto-vectorization

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

使用 AVX512 或 AVX2 计算所有打包 32 位整数总和的最快方法

我正在寻找一种最佳方法来计算 a __m256ior中所有打包的 32 位整数的总和__m512i。为了计算n 个元素的总和,我经常使用log2(n) vpadddvpermd函数,然后提取最终结果。但是,这不是我认为的最佳选择。

编辑:在速度/周期减少方面最佳/最佳。

c intrinsics avx avx2 avx512

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