[转]Restrict关键字
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
[转]Restrict关键字的更多相关文章
- restrict关键字(暗示编译器,某个指针指向的空间,只能从该指针访问)
我们希望某个对象(内存空间)不被修改的通常做法是什么?声明该空间的const类型,但是这样真的可以吗?是不是的,由于const空间对象的指针是可以付给一个非const值指针的.所以这仍然无法不让该空间 ...
- c99标准的restrict关键字
参考自restrict restrict解释 restrict关键字出现于C99标准,wiki上的解释restrict from wiki. In the C programming language ...
- [转] restrict关键字用法
PS: 在函数中,指针参数指定了restrict,表示这个指针指向的这段区域只能通过这个指针修改 c99中新增加了一个类型定义,就是restrict. 看了下网上的相关贴子,但还是问题解决的不够.下面 ...
- restrict关键字
值得注意的是,一旦你决定使用restrict来修饰指针,你必须得保证它们之间不会互相重叠,编译器不会替你检查. 关键字restrict有两个读者.一个是编译器,它告诉编译器可以自由地做一些有关优化的假 ...
- C 语言restrict 关键字的概念及使用例子
restrict是c99标准引入的,它只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式.即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不能通过其 ...
- C语言restrict关键字的使用----可以用来优化代码
C99中新增加了restrict修饰的指针:由restrict修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取.对对象的存取都限定于基于由restr ...
- DSP 中关键字extern,cregister,Near ,Far,restrict,volatile
extern:extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.另外,extern也可用来进行链接指定. const: 可以 ...
- c/c++常用的几个关键字总结
一.volatile volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据.如果没有volatile关键字,则编 ...
- ”危险“的restrict与GCC的编译优化
restrict是C99标准中新添加的关键字,对于从C89标准开始起步学习C语言的同学来说(包括我),第一次看到restrict还是相当陌生的.Wikipedia给出的解释如下: In the C p ...
随机推荐
- 2017中国人工智能公司榜单发布,颠覆AT的AI独角兽全在这
每年12月,创业邦研究中心评选并报道“中国创新成长企业100强”,这个榜单我们已经连续做了8年,是中国最有潜力的创业新贵榜,受到了业内广泛认可.从2015年开始我们发现,人工智能上榜企业明显增多,20 ...
- jqGrid属性中文详细说明
jqGrid属性中文详细说明 jqGrid的属性很多,其实很大部分的属性,使用其默认值就可以了.但是详细了解一下属性的含义以及作用,对我们定制自己的grid是有帮助的. 以下内容描述格式是:属性名称 ...
- 微信小程序对接串口摄像头
串口摄像头由树莓派控制,代码如下: # _*_ coding:utf-8 import serial import time import traceback import pycurl import ...
- 如何区别英语前缀pri,pro,per,pre?
pri- 前缀pri-来源于拉丁语的这几个形容词“prim.us”, “prim.a”, “prim.um”,表示“第一的”的意思,和“pri.or”, “pri.or”, “pri.us”,是“优先 ...
- 洛谷P2114 [NOI2014]起床困难综合症
P2114 [NOI2014]起床困难综合症 题目描述 21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm一直坚持与起床困难综合症作 ...
- BZOJ 2561 最小生成树 | 网络流 最小割
链接 BZOJ 2561 题解 用Kruskal算法的思路来考虑,边(u, v, L)可能出现在最小生成树上,就是说对于所有边权小于L的边,u和v不能连通,即求最小割: 对于最大生成树的情况也一样.容 ...
- luogu1540 [NOIp2011]机器翻译 (队列)
#include<bits/stdc++.h> #define pa pair<int,int> #define CLR(a,x) memset(a,x,sizeof(a)) ...
- 【bzoj2440】 中山市选2011—完全平方数
http://www.lydsy.com/JudgeOnline/problem.php?id=2440 (题目链接) 题意 求第K个不含有完全平方因子的数 Solution 没想到莫比乌斯还可以用来 ...
- oracle执行update语句时卡住问题分析及解决办法
转载:http://www.jb51.net/article/125754.htm 这篇文章主要介绍了oracle执行update语句时卡住问题分析及解决办法,涉及记录锁等相关知识,具有一定参考价值, ...
- 改变 小程序 select 多选框 选中图片
https://www.jianshu.com/p/11eb5b0bfe1a 注意 博客介绍的 在 wxss backgroung-image 中引入小程序内图片是不可的,传到cdn上才实现