有没有人曾见过任何数字/分析是否使用C++ restrict 关键在海湾合作委员会/g++实际提供了任何明显的性能,提高在现实中(而不只是在理论上)?

我读过各种文章建议/诋毁其使用,但我没跑过任何真正的数字实际上表明任何一方的论点。

编辑

我知道, restrict 不是正式的一部分C++,但它支持通过一些编译器和我已经读了一份由 克里斯特埃里克森 它强烈建议其使用情况。

有帮助吗?

解决方案

在限制关键字确实的差。

我看到因子2,更改进在某些情况下(图像处理)。大多数的差距并不大,虽然时间。约10%。

下面是示出了差一个小例子。我写了一个非常基本的4x4矢量*矩阵变换作为测试。请注意,我必须强迫不被内联函数。否则GCC检测,有没有在我的基准代码的任何混淆的指针和限制不会有所作为由于内联。

我可以移动的变换函数到不同的文件中。

#include <math.h>

#ifdef USE_RESTRICT
#else
#define __restrict
#endif


void transform (float * __restrict dest, float * __restrict src, 
                float * __restrict matrix, int n) __attribute__ ((noinline));

void transform (float * __restrict dest, float * __restrict src, 
                float * __restrict matrix, int n)
{
  int i;

  // simple transform loop.

  // written with aliasing in mind. dest, src and matrix 
  // are potentially aliasing, so the compiler is forced to reload
  // the values of matrix and src for each iteration.

  for (i=0; i<n; i++)
  {
    dest[0] = src[0] * matrix[0] + src[1] * matrix[1] + 
              src[2] * matrix[2] + src[3] * matrix[3];

    dest[1] = src[0] * matrix[4] + src[1] * matrix[5] + 
              src[2] * matrix[6] + src[3] * matrix[7];

    dest[2] = src[0] * matrix[8] + src[1] * matrix[9] + 
              src[2] * matrix[10] + src[3] * matrix[11];

    dest[3] = src[0] * matrix[12] + src[1] * matrix[13] + 
              src[2] * matrix[14] + src[3] * matrix[15];

    src  += 4;
    dest += 4;
  }
}

float srcdata[4*10000];
float dstdata[4*10000];

int main (int argc, char**args)
{
  int i,j;
  float matrix[16];

  // init all source-data, so we don't get NANs  
  for (i=0; i<16; i++)   matrix[i] = 1;
  for (i=0; i<4*10000; i++) srcdata[i] = i;

  // do a bunch of tests for benchmarking. 
  for (j=0; j<10000; j++)
    transform (dstdata, srcdata, matrix, 10000);
}

结果:(在我的2千兆赫的Core Duo)

nils@doofnase:~$ gcc -O3 test.c
nils@doofnase:~$ time ./a.out

real    0m2.517s
user    0m2.516s
sys     0m0.004s

nils@doofnase:~$ gcc -O3 -DUSE_RESTRICT test.c
nils@doofnase:~$ time ./a.out

real    0m2.034s
user    0m2.028s
sys     0m0.000s

在拇指20%更快的执行,上系统。

要显示多少取决于我已经让Cortex-A8的嵌入式CPU相同的代码运行的架构(调整循环计数了一下,因为我不想等那么久):

root@beagleboard:~# gcc -O3 -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp test.c
root@beagleboard:~# time ./a.out

real    0m 7.64s
user    0m 7.62s
sys     0m 0.00s

root@beagleboard:~# gcc -O3 -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -DUSE_RESTRICT test.c 
root@beagleboard:~# time ./a.out

real    0m 7.00s
user    0m 6.98s
sys     0m 0.00s

下面的区别仅仅是9%(相同的编译器顺便说一句。)

其他提示

没有限制的关键词提供显着的益处,在海湾合作委员会/g++?

它的 可以 减少的数量的指令如上面的例子中,所以使用它时,可能的。

海湾合作委员会4.8Linux x86-64exmample

输入:

void f(int *a, int *b, int *x) {
  *a += *x;
  *b += *x;
}

void fr(int *restrict a, int *restrict b, int *restrict x) {
  *a += *x;
  *b += *x;
}

汇编和编:

gcc -g -std=c99 -O0 -c main.c
objdump -S main.o

-O0, 他们都是相同的。

-O3:

void f(int *a, int *b, int *x) {
    *a += *x;
   0:   8b 02                   mov    (%rdx),%eax
   2:   01 07                   add    %eax,(%rdi)
    *b += *x;
   4:   8b 02                   mov    (%rdx),%eax
   6:   01 06                   add    %eax,(%rsi)  

void fr(int *restrict a, int *restrict b, int *restrict x) {
    *a += *x;
  10:   8b 02                   mov    (%rdx),%eax
  12:   01 07                   add    %eax,(%rdi)
    *b += *x;
  14:   01 06                   add    %eax,(%rsi) 

对新手来说, 呼吁《公约》 为:

  • rdi =第一个参数
  • rsi =第二个参数
  • rdx =第三个参数

结论: 3指示,而不是4.

当然,说明 可以有不同的延迟, 但这提供了一个很好的想法。

为什么是海湾合作委员会能够优化?

代码以上是从 维基百科的例子 这是 非常 有启发性。

伪会 f:

load R1 ← *x    ; Load the value of x pointer
load R2 ← *a    ; Load the value of a pointer
add R2 += R1    ; Perform Addition
set R2 → *a     ; Update the value of a pointer
; Similarly for b, note that x is loaded twice,
; because a may be equal to x.
load R1 ← *x
load R2 ← *b
add R2 += R1
set R2 → *b

对于 fr:

load R1 ← *x
load R2 ← *a
add R2 += R1
set R2 → *a
; Note that x is not reloaded,
; because the compiler knows it is unchanged
; load R1 ← *x
load R2 ← *b
add R2 += R1
set R2 → *b

是这真的很快点吗?

Ermmm...不是为这个简单的试验:

.text
    .global _start
    _start:
        mov $0x10000000, %rbx
        mov $x, %rdx
        mov $x, %rdi
        mov $x, %rsi
    loop:
        # START of interesting block
        mov (%rdx),%eax
        add %eax,(%rdi)
        mov (%rdx),%eax # Comment out this line.
        add %eax,(%rsi)
        # END ------------------------
        dec %rbx
        cmp $0, %rbx
        jnz loop
        mov $60, %rax
        mov $0, %rdi
        syscall
.data
    x:
        .int 0

然后:

as -o a.o a.S && ld a.o && time ./a.out

在Ubuntu14.04AMD64CPU英特尔i5-3210M.

我承认,我仍不了解现代化的Cpu。让我知道如果你:

  • 找到一个缺陷,在我的方法
  • 发现了一个汇编试验的情况下,它变得快得多
  • 明白为什么没有一个差异

的制品揭秘restrict关键字是指为什么程序员指定别名的纸张是一个坏主意( PDF),其表示,它通常没有帮助,并提供测量结果来支持这一行动。

请注意,C++编译器,允许 restrict 关键词仍然可以忽略它。这种情况为例 在这里,.

我测试 C-程序。如果没有restrict花了12.640秒完成,与restrict 12.516。看起来像它的可以保存一些时间。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top