相关疑难解决方法(0)

为memcpy增强了REP MOVSB

我想使用增强的REP MOVSB(ERMSB)为自定义获得高带宽memcpy.

ERMSB引入了Ivy Bridge微体系结构.如果您不知道ERMSB是什么,请参阅英特尔优化手册中的"增强型REP MOVSB和STOSB操作(ERMSB)" 部分.

我知道直接执行此操作的唯一方法是使用内联汇编.我从https://groups.google.com/forum/#!topic/gnu.gcc.help/-Bmlm_EG_fE获得了以下功能

static inline void *__movsb(void *d, const void *s, size_t n) {
  asm volatile ("rep movsb"
                : "=D" (d),
                  "=S" (s),
                  "=c" (n)
                : "0" (d),
                  "1" (s),
                  "2" (n)
                : "memory");
  return d;
}
Run Code Online (Sandbox Code Playgroud)

然而,当我使用它时,带宽远小于memcpy. 使用我的i7-6700HQ(Skylake)系统,Ubuntu 16.10,DDR4 @ 2400 MHz双通道32 GB,GCC 6.2,__movsb获得15 GB/s并memcpy获得26 GB/s.

为什么带宽如此低REP MOVSB?我该怎么做才能改善它?

这是我用来测试它的代码.

//gcc -O3 -march=native -fopenmp foo.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gcc memcpy

56
推荐指数
4
解决办法
1万
查看次数

为什么矢量化循环没有性能改进

我正在调查矢量化对程序性能的影响.在这方面,我写了以下代码:

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>

#define LEN 10000000

int main(){

    struct timeval stTime, endTime;

    double* a = (double*)malloc(LEN*sizeof(*a));
    double* b = (double*)malloc(LEN*sizeof(*b));
    double* c = (double*)malloc(LEN*sizeof(*c));

    int k;
    for(k = 0; k < LEN; k++){
        a[k] = rand();
        b[k] = rand();
    }

    gettimeofday(&stTime, NULL);

    for(k = 0; k < LEN; k++)
        c[k] = a[k] * b[k];

    gettimeofday(&endTime, NULL);

    FILE* fh = fopen("dump", "w");
    for(k = 0; k < LEN; k++)
        fprintf(fh, "c[%d] = %f\t", k, c[k]);
    fclose(fh);

    double …
Run Code Online (Sandbox Code Playgroud)

c performance simd icc

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

从两个数组的点积测量内存带宽

两个数组的点积

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

不重用数据,因此它应该是一个内存绑定操作.因此,我应该能够从点积测量内存带宽.

使用代码 为什么 - 矢量化 - 循环 - 没有性能改进 我的系统带宽为9.3 GB/s.但是,当我尝试使用点积计算带宽时,我获得单个线程的速率的两倍以及使用多个线程的速率超过三倍(我的系统有四个核心/八个超线程).这对我没有意义,因为内存绑定操作不应该受益于多个线程.以下代码的输出如下:

Xeon E5-1620, GCC 4.9.0, Linux kernel 3.13
dot 1 thread:      1.0 GB, sum 191054.81, time 4.98 s, 21.56 GB/s, 5.39 GFLOPS
dot_avx 1 thread   1.0 GB, sum 191043.33, time 5.16 s, 20.79 GB/s, 5.20 GFLOPS
dot_avx 2 threads: 1.0 GB, sum 191045.34, time 3.44 s, 31.24 GB/s, 7.81 GFLOPS
dot_avx 8 threads: 1.0 GB, sum 191043.34, time 3.26 …
Run Code Online (Sandbox Code Playgroud)

c++ memory bandwidth openmp avx

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

R在进行矢量化计算时是否利用SIMD?

在R中给出这样的数据帧:

+---+---+
| X | Y |
+---+---+
| 1 | 2 |
| 2 | 4 |
| 4 | 5 |
+---+---+
Run Code Online (Sandbox Code Playgroud)

如果对此数据帧执行矢量化操作,如下所示:

data$Z <- data$X * data$Y
Run Code Online (Sandbox Code Playgroud)

这会利用处理器的单指令多数据(SIMD)功能来优化性能吗?这似乎是一个完美的案例,但我找不到任何证实我的预感的东西.

r simd vectorization

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

在GCC中生成没有cmp指令的循环

我有许多紧凑的循环,我正在尝试使用GCC和内在函数进行优化.考虑例如以下功能.

void triad(float *x, float *y, float *z, const int n) {
    float k = 3.14159f;
    int i;
    __m256 k4 = _mm256_set1_ps(k);
    for(i=0; i<n; i+=8) {
        _mm256_store_ps(&z[i], _mm256_add_ps(_mm256_load_ps(&x[i]), _mm256_mul_ps(k4, _mm256_load_ps(&y[i]))));
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生这样的主循环

20: vmulps ymm0,ymm1,[rsi+rax*1]
25: vaddps ymm0,ymm0,[rdi+rax*1]
2a: vmovaps [rdx+rax*1],ymm0
2f: add    rax,0x20
33: cmp    rax,rcx
36: jne    20 
Run Code Online (Sandbox Code Playgroud)

但是cmp指令是不必要的.而不是具有rax在零开始和结束在sizeof(float)*n我们可以设置基指针(rsi,rdi,和rdx),以阵列的端部,并设置rax-sizeof(float)*n然后测试为零.我可以用我自己的汇编代码这样做

.L2  vmulps          ymm1, ymm2, [rdi+rax]
     vaddps          ymm0, ymm1, [rsi+rax]
     vmovaps         [rdx+rax], ymm0 …
Run Code Online (Sandbox Code Playgroud)

c optimization assembly gcc intrinsics

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

矢量化 - SSE、AVX 和 AVX2 预计加速

我正在使用以下处理器 i7 在 MacOS 上进行矢量化基准测试:

$ sysctl -n machdep.cpu.brand_string

Intel(R) Core(TM) i7-4960HQ CPU @ 2.60GHz
Run Code Online (Sandbox Code Playgroud)

我的 MacBook Pro 是 2014 年中期的。

我尝试使用不同的标志选项进行矢量化:我感兴趣的 3 个是 SSE、AVX 和 AVX2。

对于我的基准测试,我将 2 个数组的每个元素相加,并将总和存储在第三个数组中。

我必须让您注意到我正在使用double这些数组的类型。

以下是我的基准代码中使用的函数:

1*) 首先使用 SSE 矢量化:

#ifdef SSE
#include <x86intrin.h>
#define ALIGN 16
void addition_tab(int size, double *a, double *b, double *c)
{

 int i;
 // Main loop
 for (i=size-1; i>=0; i-=2)
 {
  // Intrinsic SSE syntax
  const __m128d x = _mm_load_pd(a); // Load two x elements
  const …
Run Code Online (Sandbox Code Playgroud)

c sse vectorization avx avx512

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

AVX标量操作要快得多

我测试了以下简单的功能

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

具有非常大的数组,因此它受内存带宽限制.我使用的测试代码如下.当我用-O2它编译它需要1.7秒.当我用-O2 -mavx它编译它只需要1.0秒.非vex编码的标量操作慢了70%!为什么是这样?

这里是为大会-O2-O2 -mavx. <code> -O2 </ code>和<code> -O2 -mavx </ code>的vimddif

https://godbolt.org/g/w4p60f

系统:i7-6700HQ@2.60GHz(Skylake)32 GB内存,Ubuntu 16.10,GCC 6.3

测试代码

//gcc -O2 -fopenmp test.c
//or
//gcc -O2 -mavx -fopenmp test.c
#include <string.h>
#include <stdio.h>
#include <x86intrin.h>
#include <omp.h>

#define N 1000000
#define R 1000

void mul(double *a, double *b) {
  for (int i = 0; i<N; i++) a[i] …
Run Code Online (Sandbox Code Playgroud)

c memory x86 sse avx

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

标签 统计

c ×5

avx ×3

assembly ×2

gcc ×2

memory ×2

simd ×2

sse ×2

vectorization ×2

x86 ×2

avx512 ×1

bandwidth ×1

c++ ×1

icc ×1

intrinsics ×1

memcpy ×1

openmp ×1

optimization ×1

performance ×1

r ×1