Bạn tham khảo đề tài đã được đưa ra từ trước tại: Từ khóa restrict trong chuẩn C99 có tác dụng gì
Nói một cách đơn giản là khi khai báo có thêm từ khóa restrict biến đó sẽ không align. Bạn hiểu về align thì sẽ hiểu được restrict thôi.
các pro cho em hỏi từ khóa __restrict trong C hay là C++ có tác dụng gì, em đọc mấy bài trên mạng mà em thấy khó hiểu quá.
//Em dùng VS trên windows
Thanks.
Bạn tham khảo đề tài đã được đưa ra từ trước tại: Từ khóa restrict trong chuẩn C99 có tác dụng gì
Nói một cách đơn giản là khi khai báo có thêm từ khóa restrict biến đó sẽ không align. Bạn hiểu về align thì sẽ hiểu được restrict thôi.
Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó.Email: kevin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
Phone: 0972 89 7667
Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp hoặc bị sự thiếu kỷ luật làm tiêu tan sự nghiệp.
ok, thanks anh.
anh sửa lại cái ví dụ này đi:
(code này của anh ở cái link)
có restrict hay ko có đều sinh ra cùng một mã asm, ví dụ này không có tác dụng.Code:int n = 3; int* restrict a1; int* restrict a2; int* t = malloc(2 * n * sizeof(int)); a1 = t; // nửa đầu của t a2 = t + n; // nửa sau của t
Ặc ặc mình vẫn hiểu từ khóa restrict là anti-alias chứ nhỉ :( sao lại liên quan đến align ở đây
Nhưng đúng là nó không có nhiều tác dụng và hầu như không bao giờ gặp nên tốt nhất là không quan tâm vội
Mình giải thích tạm theo cách mình hiểu nhé (sai sót các bạn góp ý giúp mình). Đầu tiên mình giải thích khái niệm alias:
Giả sử mình có 2 mảng a, b kiểu int[10] và 1 hàm inverse(b, a) gán b là mảng thứ tự ngược của a
vậy, trong trường hợp biết a và b là 2 mảng độc lập (no-alias) thì bạn có thể for i = 0->9: b[i] = a[9 - i]
Nhưng khi bạn gọi inverse(a, a) sẽ sai!!! vì trường hợp này a và b không độc lập (alias)
Vậy khi implement hàm inverse này, nếu bạn biết a và b là no-alias thì sẽ dễ dàng và hiệu quả hơn
Tương tự, khi khai báo 1 poiner là restricted thì compiler sẽ biết vùng nhớ được pointer đó trỏ đến hoàn toàn độc lập, không chồng chéo gì đến vùng nhớ khác (no-alias) ==> trong 1 số trường hợp compiler sẽ có thể dịch ra code tối ưu hơn. Nhưng những trường hợp nào tối ưu được hơn thì mình chịucó vẻ rất ít, hoặc là 1 tính năng dự phòng cho tương lai là chính
Edit: viết xong mới google, thấy ví dụ để compiler có thể dịch được code tốt hơn nè:
http://en.wikipedia.org/wiki/Restrict
Đã được chỉnh sửa lần cuối bởi fbchicken : 04-08-2011 lúc 11:39 PM.
ok, thank you. Nhưng cho mình hỏi thêm một câu nữa : tham số truyền vào hàm inverse thực chất là một con trỏ, nhưng không biết kích thước vùng dữ liệu, làm sao trình dịch biết 2 con trỏ có chồng lên nhau không.
@pkthanh92:
- restrict không có tác dụng nếu không phải là chuẩn C99
- Trong VC++ là __restrict
- Trong gcc là __restrict__
@fbchicken: Cảm ơn bạn, ở trên mình viết nhầm. Nhưng bạn đã viết rõ ràng rồi mình không cần sửa lại.
-----------------------------
Còn một đặc điểm của restrict là: Không có con trỏ khác restrict có thể truy cập vào vùng nhớ được trỏ đến bởi restrict. Nghĩa là nếu đã vùng nhớ đã được trỏ bởi con trỏ restrict thì các con trỏ loại khác sẽ không thể truy cập.
Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó.Email: kevin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
Phone: 0972 89 7667
Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp hoặc bị sự thiếu kỷ luật làm tiêu tan sự nghiệp.
Mình chưa biết tính chất này. Vừa test thử trên gcc thì thấy 2 con trỏ, 1 restrict 1 không, cùng trỏ đến 1 địa chỉ, vẫn đọc/ghi bình thường
Nhưng thôi, mình cũng không quan tâm vì có vẻ nó ít ứng dụng!
Cũng gặp qua 1 vài thư viện có sử dụng từ khóa này nhưng rất ít. Với cả, mình sử dụng những thư viện đó cũng chẳng cần quan tâm nó implement thế nào![]()
Dự đoán cả đời chưa chắc đã viết 1 đoạn code nào cần dùng restrict để tối ưu hóa cả. hihi.
(dịch lại wiki)
khi khai báo một hàm có 2 tham số là con trỏ restrict, thì trình biên dịch coi như 2 con trỏ đó không trỏ cùng một đối tượng. Code sinh ra sẽ ngắn hơn -> nhanh hơn.
em làm thử một ví dụ trên VS thế này.
so sánh kết quả:
Visual C++ Code:
#include <stdio.h> #include <conio.h> void foo1(unsigned long* pa, unsigned long* pb, unsigned long* pc) { *pa+= *pc; *pb+= *pc; } void foo2(unsigned long* __restrict pa, unsigned long* __restrict pb, unsigned long* __restrict pc) { *pa+= *pc; *pb+= *pc; } int main() { unsigned long a, b, *c; c = &a; a = 2; b = 1; foo1( &a, &b, c ); printf( "\na= %d ; b = %d ", a, b ); a = 2; b = 1; foo2( &a, &b, c ); // viết foo2( &a, &b, &a ) thì thô thiển quá, sợ trình dịch nó xóa mất, dùng thông qua biến c cho chắc ăn printf( "\na= %d ; b = %d ", a, b ); return 0; }
output:
đầu tiên là phát hiện ra lỗi của diễn đàn không bôi đen từ __restrictCode:a= 4 ; b = 5 a= 4 ; b = 5
sau đó là nếu cứ theo lý thyết trên thì phải ra 2 kết quả khác nhau ( vì khi gọi foo2, chạy đến dòng *pb+= *pc; thì comiler không cần tham chiếu đến ô nhớ trong pc mà lấy luôn giá trị *pc trước đó).
đo thời gian
Visual C++ Code:
#include <Windows.h> #include <stdio.h> #include <conio.h> void foo1(unsigned long* pa, unsigned long* pb, unsigned long* pc) { *pa+= *pc; *pb+= *pc; } void foo2(unsigned long* __restrict pa, unsigned long* __restrict pb, unsigned long* __restrict pc) { *pa+= *pc; *pb+= *pc; } int main() { DWORD dT, i, j; unsigned long a, b, *c; c = &a; printf( "\nnormal - restrict "); for( j = 0; j < 10; j++) { a = 1; b = 0; dT = GetTickCount(); for( i = 0; i < 500000; i++) foo1( &a, &b, c ); dT = GetTickCount() - dT; printf( "\n %d - ", dT ); a = 1; b = 0; dT = GetTickCount(); for( i = 0; i < 500000; i++) foo2( &a, &b, c ); dT = GetTickCount() - dT; printf( " %d", dT ); } _getch(); return 0; }
output:
-> coi như bằng nhauCode:normal - restrict 16 - 16 15 - 31 16 - 16 15 - 16 15 - 16 16 - 15 16 - 15 16 - 16 0 - 15 31 - 16
ai giải thích dùm em với, sao 2 test ở trên lại ko đúng theo lý thuyết vậy, thanks.
Có mấy điều như sau:
1. Dùng clock của windows để đo performance, với giá trị in ra < 20 đều coi như vô nghĩa. (google gettickcount precision accuracy để hiểu rõ hơn) Bạn có thể dùng CPU clock (google lệnh rdtsc), hoặc dùng linux, hoặc tăng số vòng lặp để đạt hiệu số clock ít nhất vài trăm.
2. Do windows không real-time nên đo đạc sẽ bị sai số nhất định, phụ thuộc rất nhiều vào điều kiện thời tiết
3. Lợi ích đạt được (1 CPU instruction) sẽ không thấy được khi trong cùng vòng lặp có quá nhiều CPU instruction khác (inc i, compare, function call - đặc biệt chi phí cho function call rất cao). Muốn thể hiện được lợi ích của restrict thì bạn phải đảm bảo function được inline. Nói chung để đo những cái tương tự, bạn nên chạy 1 lần (function inline) và dùng asm + lệnh rdtsc để đo số CPU clock là ổn nhất
4. 1 số compiler trực tiếp bỏ qua từ khóa restrict, tức là coi như nó không tồn tạiBạn google xem VC++ xử lý từ khóa đó thế nào. Với hiện tượng 2 kết quả như nhau thì có vẻ VC++ cũng bỏ qua rồi
Đã được chỉnh sửa lần cuối bởi fbchicken : 10-08-2011 lúc 02:23 AM.