Tải bản đầy đủ - 0 (trang)
IX.6 Tránh hiệu ứng Race.

IX.6 Tránh hiệu ứng Race.

Tải bản đầy đủ - 0trang

1) Các thread vẫn thực hiện cơng việc của mình, chỉ cần có duy nhất một thread (khơng

rõ là thread nao) đi qua vùng đơn lẻ.



Đối với trường hợp này có thể dùng chỉ thị

#pragma omp single



thơng báo khúc lệnh sau đó là chỉ do một thread nào đó thực hiện.

Trong ví dụ sau tất cả các thread chạy song song với S1(), chỉ có một thread thực hiện

S2(), và sau đó chúng thực hiện song song với S3().

Sơ đồ khối

#pragma omp sections nowait

{ work_S1();

#pragma omp single

work_S2();

work_S3();

}



Trình minh họa

#include

#include

#define NUM_THREADS 2

main ()

{ omp_set_num_threads(NUM_THREADS);

#pragma omp parallel

{ cout<< "a";

#pragma omp single

cout << "2";

cout<< "b";

}

}

// aa2bb



Số “2” chỉ xuất hiện duy nhất 1 lần, do chỉ có 1 thread đi qua vùng lệnh ấy.



Chỉ thị

#pragma omp single



cho biết lệnh tiếp theo sẽ chỉ có một thread nào đó thực hiện (các thread khác vẫn sẽ làm

tiếp phần việc của mình). Các thread sẽ phải chờ nhau, để cùng khỏi vùng “single”.

2) Các thread vẫn thực hiện cơng việc của mình, chỉ cần master đi qua vùng đơn lẻ.

Sơ đồ

#pragma omp sections nowait

{ work_S1();

#pragma omp master

work_S2();

work_S3();

}



Trình minh họa

#include

#include

#define NUM_THREADS 2

main ()

{

omp_set_num_threads(NUM_THREADS);

#pragma omp parallel

{ cout<< "a";

#pragma omp master

{int id; id = omp_get_thread_num();

cout << id ;

}

cout<< "b";

}

}

// aa0bb



Số 0 ứng với số hiệu của “master”

chỉ thị

#pragma omp master



thông báo lệnh tiếp theo sẽ chỉ có master thread thực hiện. Các thread khơng phải chờ để

cùng nhau ra khỏi vùng master.



3) Tất cả các thread đều phải đi qua một vùng lệnh và đi tuần tự (nhưng không nhất thiết

phải theo đúng thứ tự)



Nếu có 3 phần cơng việc: phần thứ nhất S1 và thứ ba S3 có thể thực hiện song song,

nhưng phần thứ hai S2 thì phải thực hiện một cách tuần tự, nhưng tất cả các thread đều

phải thự hiện (tức là phải đi qua vùng ấy). Việc này có thể thực hiện nhờ cấu trúc vùng

lệnh tuần tự với khai báo “critical”

Sơ đồ

#pragma omp sections nowait

{ work_A();

#pragma omp critical

work_B();

work_C();

}



Trình minh họa

#include

#include

#define NUM_THREADS 2

main ()

{ omp_set_num_threads(NUM_THREADS);

#pragma omp parallel

{cout<< "a";

#pragma omp critical

{int id;

id = omp_get_thread_num();

cout << id ;

}

cout<< "b";

}

}

//a0ba1b



Các chữ số 0 và 1 cho thấy các thread đều đi qua vùng lệnh tuần tự “critical”

Chỉ thị

#pragma omp critical



thông báo tất cả các thread đều phải thực hiện khúc lệnh sau đó – đi qua vùng này –

nhưng phải đi qua một cách đơn lẻ. Đơn lẻ ở đây khơng có ý là chúng, tức là các thread,

phải tn thủ một thứ tự nào đó để đi qua, mà là, thread nào tới trước thì sẽ qua trước.

Nhiều khi chỉ cần ra chỉ thị để một lệnh nào đó – chỉ một, khi (một thread) đang thực

hiện thì các thread khác không được xen vào, chúng ta dùng chỉ thị

#pragma omp atomic



Với chỉ thị này, sẽ khơng có một thread nào cắt ngang quá trình thực hiện lệnh ngay sau

nó. Chỉ thị này được dùng để tránh việc phải khai báo cả một vùng lệnh là CS (critical

section)

Trong ví dụ tính gần đúng số  sau đây, chỉ thị #pragma omp critical được dùng để cho

tất cả các thread đều có thể cộng kết quả tính được vào một ô nhớ (thứ tự cộng trước hay

cộng sau không quan trọng!)

#include

static long num_steps = 100000;

double step;

#define NUM_THREADS 2

void main ()

{

int i;

double x, sum, pi=0.0;

step = 1.0/(double) num_steps;

omp_set_num_threads(NUM_THREADS)

#pragma omp parallel private (x, sum)

{

id = omp_get_thread_num();

for (i=id,sum=0.0;i< num_steps;i=i+NUM_THREADS){

x = (i+0.5)*step;

sum += 4.0/(1.0+x*x);

}

#pragma omp critical

pi += sum

}

}



IX.7 Giải phương trình vi phân.

IX.7.1. Thuật tốn song song Hammer-Hollingsworth.

OpenMP – là một cơng cụ lập trình hiệu quả trong các tính tốn kỹ thuật. Sau đây là ví

dụ giải phương trình vi phân y' 1  x  y với y(0.1) 0.1 , theo thuật tốn song song

Hammer-Hollingsworth. Trình được viết để chạy trên máy có từ 2 vi-xử-lý trở lên,

Phương tình có nghiệm y(x ) 2.2e x  0.1  x  2 tại điểm x 1.09 thì y(1.09) 2.83072 .

#include

#include

#include

double f(double x,double y)

{double s = 1.0+ sin(y+x);

return s;

}

void main()

{ double tstart,tend;

double x, y, h, u, v, a11, a12, a21, a22, b1, b2, c1, c2;

a11=1.0/4; a22=1.0/4; a21=1.0/4+sqrt(3)/6; a12=1.0/4-sqrt(3)/6;

b1=1.0/2; b2=1.0/2; c1=1.0/2+sqrt(3)/6; c2=1.0/2-sqrt(3)/6;

h=1.0/100.0; x=0.1; y=0.1;

tstart=omp_get_wtime();

u=y; v=y;

for (int i=1; i<100; i++)

{ for (int j=1; j<4; j++)

{

#pragma omp parallel

#pragma omp sections nowait

{

#pragma omp section

u1=y+h*(a11*f(x+c1*h,u)+a12*f(x+c2*h,v));

#pragma omp section

v1=y+h*(a21*f(x+c1*h,u)+a22*f(x+c2*h,v));

}

u=u1; v=v1;

}

y+=h*(b1*f(x+c1*h,u)+b2*f(x+c2*h,v));

x+=h;

}

tend=omp_get_wtime();

cout<<"tuan tu " << tend - tstart<<"\n"; cout << x << " " << y << "\n";

}



Vòng lệnh “for”



for (int j=1; j<4; j++)

{

#pragma omp parallel

#pragma omp sections nowait

{

#pragma omp section

u1=y+h*(a11*f(x+c1*h,u)+a12*f(x+c2*h,v));

#pragma omp section

v1=y+h*(a21*f(x+c1*h,u)+a22*f(x+c2*h,v));

}

u=u1; v=v1;

}



được dùng để tìm điểm bất động

u0  y,



v0  y



uk 1  y  (a11 f (x  c1, uk )  a12 f (x  c 2 , vk ))



k 0,1,2,3



vk 1  y  (a 21f (x  c1, uk )  a 22f (x  c 2 , vk ))



k 0,1,2,3



Trong đó, các lệnh

#pragma omp parallel

#pragma omp sections nowait

{

#pragma omp section

....

// thread 0

#pragma omp section

....

// thread 1

}



tạo ra 2 thread chạy song song với nhau (trên máy có 2 vi-xử-lý thì mỗi thread sử dụng 1

vi-xử-lý). Thread thứ nhất tính uk 1  y  (a11f (x  c1, uk )  a12 f (x  c 2 , vk )) , và

thread thứ hai tính vk 1  y  (a 21f (x  c1, uk )  a 22 f (x  c 2 , vk )) .

Khi ra khỏi vùng song song này, trình sẽ chạy tuần tự, và vì thế mà lệnh

u=u1; v=v1;



chỉ do thread master thực hiện (hiện tượng race sẽ không xảy ra).

Để thấy được ý nghĩa của các lệnh gán gián tiếp trên (tránh được hiện tượng race),

chúng ta sử dụng các lệnh gán trực tiếp (sẽ gây ra hiện tượng race!).

for (int j=1; j<4; j++)

{

#pragma omp parallel

#pragma omp sections nowait

{



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

IX.6 Tránh hiệu ứng Race.

Tải bản đầy đủ ngay(0 tr)

×