0 定义

C99中新增加的用于修饰指针的关键字,用于表示该指针所指向的内存,只有通过该指针访问得到(如下ptr指向的内存单元只能通过ptr访问得到)。从而可以让编译器对代码进行优化,生成更有效率的汇编代码。

char *restrict ptr;

  

1 优化举例

举例1,如下代码(引自参考1),以及翻译成汇编之后的代码。

#include <stdio.h>

#ifdefRES
void multi_add(int* restrict p1, int* restrict p2, int* restrict pi)
#else
void multi_add(int* p1, int* p2, int* pi)
#endif {
  *p1+= *pi;
  *p2+= *pi;
} int main()
{
  int a =1, b = 2;
  int inc =1;
  // increase both aand b by 1
  multi_add(&a,&b, &inc);
  // print the result
  printf("a= %d, b = %d\n", a, b); }

         调用mulit_add函数时,翻译成汇编后的代码,如果是没有RES,则是

mov(%rdx),%eax
add%eax, (%rdi)
mov(%rdx),%eax
add%eax, (%rsi)

        相反如果有RES定义,则是

mov(%rdx),%eax
add %eax,(%rdi)
add %eax,(%rsi)

  

因为pi是由restrict关键字修饰的,所以认为pi所指向的内存只可能通过pi访问,不可能其它 alias能访问到。所以没有必要每次都mov操作。

举例2

int ar[10];
int *restrict restar =(int *)malloc(10* sizeof(int));
int *par =ar; for (n =0; n< 10; n++)
{
  par[n]+= 5;
  restar[n]+= 5;
  ar[n]*= 2;
  par[n]+= 3;
  restar[n]+= 3;
}

  

同样由于restar 是用restrict修饰的,所以编译器会优化成restar[n] += 8;

其实优化的本质上就是使用了一系列这寄存器,而传统架构上的使用Cache(可以参见https://www.zhihu.com/question/41653775)。

2 使用举例
       用restrict修饰的指针,最多的是用来作为参数、memcpy中的src和dst就是使用restrict修改的,所以个人总结出来的用途主要在于copy操作过程中,不用每个字节每个字节去取址计算操作,而是直接page操作的可能。大大提升了性能。

3 注意点
       首先,有可能反汇编后的代码,并不能达到遇期的优化效果,这是因为gcc中指定的优化等级不对,或者根本没有指定优化等级。所以为了让编译器识别并优化restrict关键字,必须编译时指定优化等级。如在1中的举例,如果multi_add(&a,&b,&a);调用,那么在不同等级优化下的效果,如下表所示。

优化等级  最终值 原因
不优化 a = 2; b = 4; Gcc在没有开-O优化时是不会对restrict关键字优化
-O1 A=2;b=3; restrict关键字的优化
-O2及以上 a=2;b=4; Multi_add函数不再被main调用

然后,restrict关键字,不仅是告诉编译器优化代码,而且还对使用者(程序员)提出了要求,即必须保证restrict指针指向的内存,只能通过该指针访问。(记住这点是要求程序员的,编译器无法识别出报warning之类的信息)。因此,如下的代码,都可能是有问题的。

float x[100];
float *c;
void f(int n, float *restrict a, float *const b){
  int i;
  for (i =0; i < n; i++)
    a[i]= b[i]+ c[i];
} void g3(void){
  float d[100],e[100];
  c =x; f(100,d, e);// OK
  f(50,d, d +50); // OK
  f(99,d + 1, d);// undefined behavior
  c =d; f(99,d + 1, e);// undefined behavior
  f(99,e, d +1); //

         最后,restrict的指针不能赋值给另一个restrict的指针,如下。但是,restrict的指针可以赋值给一个非restrict的指针。

int* restrict p1 =&a;
int* restrict p2 =&b;
p1 =p2; //undefined behavio void f(int n, float *restrict r, float *restrict s){
  float *p = r,*q = s; //OK
  while (n--> 0) *p++ = *q++;// almost certainly optimized just like *r++= *s++
}  

  

4 参考文献

[0] http://blog.csdn.net/nathan_wz/article/details/8274451

[1] http://en.cppreference.com/w/c/language/restrict

 

最新文章

  1. OData Client Code Generator
  2. Windows Azure Virtual Machine (27) 使用psping工具,测试Azure VM网络连通性
  3. git 解决fatal: Not a git repository
  4. BZOJ 1251: 序列终结者
  5. JS中级 - 02:表单、表格
  6. wifi参考网站
  7. PSR : php编码规范
  8. 改善过多的if else
  9. ubuntu12.04 修复Grub2
  10. Ms SQLServer中的Union和Union All的使用方法和区别
  11. What is SaaS?
  12. Metrics监控应用
  13. php 使用操作符
  14. Android 4.0以后正确的获取外部sd卡存储目录
  15. HDU Be the Winner [Anti-SG]
  16. java实现找一个数范围内所有的一
  17. pymysql 详解
  18. call、apply、bind
  19. git+webpack项目初始化&lt;一&gt;
  20. poj 3279 Fliptile(二进制搜索)

热门文章

  1. PAT甲题题解-1033. To Fill or Not to Fill (25)-模拟
  2. PAT甲题题解1098. Insertion or Heap Sort (25)-(插入排序和堆排序)
  3. linux第三章学习笔记
  4. Eclipse,代码中有错误,项目中却不显示红叉
  5. Spark 实践——基于 Spark MLlib 和 YFCC 100M 数据集的景点推荐系统
  6. 统计nginx日志的状态码
  7. UML时序图学习
  8. Java微信二次开发(二)
  9. BZOJ 3174 拯救小矮人(贪心+DP)
  10. suse11/12关闭防火墙