OpenMP API ืืื ืืืกืฃ ืืืื ืฉืืืคืฉืจืื ืชืื ืืช ืืงืืืื ืืฉืคืช c ื cpp ืืฉืคืืช ื ืืกืคืืช.
pthreads ืืื ืขืืืื ืืืื ืืขืืืฃ ืืืืื ืช ืืืฆืืขืื ืืืืืฉืืช. ืขื ืืืช, ืืืืื ืช ืจืืช ืืืืกืืจืงืฆืืื ืืื ืืืืช ืืืชืื ืช ืขื ืืืฆืืขืื ืืืืื ืขืืืจ ืืจืื ืชืื ืืืช ืขืืฆืื ืืงืืืืืืช. ืืื ืืงืจื, ื ืืชื ืืืชืื ืงืื ืฉืืฉืื ืืื ืืฉื ืืื.
OpenMP ืืชืืืฉืช ืขื ืืื ืฉืืืืช ื software stack, ืืจืืืืื ืืกืืกืืื ืฉื OpenMP ืื compiler directives, OpenMP library ื- environment variables.

ื ืกืชืื ืขื ืงืื hello world ืืืืืื ื OpenMP:
#include <omp.h>
#include <stdio.h>
int main() {
#pragma omp parallel
{
printf(" hello ");
printf(" world\n ");
}
return 0;
}
ืืฉืืจื pragma omp parallel ืืื ืื ืืืืช ืืงืืืคืืืืจ.
ืืืืืง ืืคื ืื ืืืื ืืืืืช ืขื ืฉืืจืช ืื ืืกื ืืืช ืืฉืืจืช ืืฆืืื ืืืช. ืืืืืง ืฉืืคื ืื ื ืงืจื parallel region.
ื ืืื ืืช ืคืื ืืชืืื ืืช:
ืจืืฉืืช, ื ืฉืื ืื ืฉืงืืืคืื ื ืขื ืืืื fopenmp.
ืื ืืื ืฉืืืืจ ืgcc ืืืชืืืืก ืdirectives ืฉืืืืจื ื ืืงืื (ืืืงืจื ืืื ืืฉืืจื pragma omp parallel).
ื ืชื ื ืืืจืื ื- gcc ืืืจืืฅ ืืช ืืงืื ืฉื- block ืืืงืืื ืขื ืืกืคืจ default ืฉื threads, ืฉืฉืืื (ืืืจื ืืื) ืืืกืคืจ cores ืฉืืฉ ืืืืฉื ืืคืื ืืกืคืจ ื Hardware threads ืฉืืฉ ืืื core. ืืื ืืงืื ืืืงืจื ืืื, ืืชืืฆืข ืืืงืืื ืข"ื 4 threads ืืื ืื ื ืจืืืื 4 ืืืคืกืืช ืฉื hello world.
ืืื ืืงืื ืืืืข ืืคืืจื ืขื ืืจืืืืงืืืจืช ืืืืฉื ืฉืืจืฉืืชื ื ื ืืื ืืืฉืชืืฉ ืืคืงืืืช lscpu. ืื ื ืจืฆื ืจืง ืืช ืืกืคืจ ืืืืืืช ื ืฉืชืืฉ ืืคืงืืืช nproc

num of threads:
ืืื ืืืืืืจ ืืื threads ื ืจืฆื ืืื ืืืจืืฅ ืงืืข ืงืื ืืงืืืื ื ืฉืชืืฉ ืืคืงืืื omp_set_num_threads(n) ืืคื ื ืคืชืืืช ืืืืืง.
ืืื ืืงืื ืืช ืืืืื ืฉื ืื thread ื ืจืืฅ ืืช ืืคืงืืื omp_get_thread_num .
ืืืืคื ืกืืืชื ืืคืฉืจ ืืชืืจ ืชืืื ืืช ืืืฉืชืืฉืช ื pragma ืืืืคื ืืื-

Fork-Join parallelism:
ืงืืขืื ืืกืืืืื ืืืงืื ืืืืงืืืื, ืงืืข ืงืื ืืงืืืื ืืื ืืชืืื ืจืง ืืืฉืจ ืงืืข ืงืื ืืงืืืื ืืงืืื ืื ืืกืชืืื. ืืื ืื ืฉื ืฉืืื ืื ืืื ืฉืืชืืื ืืช ืืชืืืื ืthread ืืืื ืฉื ืงืจื master thread ืื main ืืืื ื ืืืฆืืื ืื ืืงืืขืื ืืืงืืืืืื.

ื ืจืื ืืื ืืืฉืืื ืืืืคื ืกืืจืชื ืืขื OMP ืืช ืื ืืกืื ืฉื ืงืืืข ืืืืืจ
ืืืืฉืื ืืฆืืจื ืกืืจืชืืช ืืื ืคืฉืื
double seq_euler_mascheroni() {
double sum = 0;
for( int i = 1; i < N; i ++){
sum+= 1.0/i;
}
return log(N) - sum;
}
ืืขืช ื ืฉืืื ืืืจืกื ืืืงืืืืืช
double sum = 0;
#pragma omp_parallel
{
const int num_threads = omp_get_num_threads();
double thread_sum = 0;
int tid = omp_get_thread_num + 1;
for(int i= tid; i < N; i+= num_threads) {
threads_sum += 1.0/i;
}
#pragma omp critical
sum += thread_sum
}
ืื ื ืืฆืข benchmark ืืืืฆืขืืช ืืคืื ืงืฆืื omp_get_wtime ื ืงืื ืืื ืจืืฆื ืฉืืฉืืขืืชืืช ืืืชืจ ืืืืจ ืืืืืืจืืชื ืืืงืืืื

ื ืกืชืื ืขื ืงืื ืกืืจืชื ืืืงืืืื ืืกืืืืช ืืขืจื


ืืืืืืจืืชื ืืืงืืืื ืืืฉื ืืช ืืกืืืืื ืืืืงืืื ืืืืกืืฃ ืืืืจ ืืช ืืื ืืืื. ื ืฉืื ืื ืฉืืื ืืฉืชืืฉ ืคื ืืคืงืืืช omp single ืฉืืืช ืคืงืืื ืฉืืืคืฉืจืช ืจืง ืthread ืืื ืืืื ืก ืืืื ืืืืืจ ืืื ืื ืืื ืืกื ืืืชืจ threads ืืงืืข ืืงืื ืืื (ืื ืื ืืืื ื ืืฉืชืืฉืื ื OpenMP ืืืชืื ืืืจ ืืื ืืื ืืืจืฉ ืื ืื ืื ืืฉืื ื). ืืฉืืืืฉ ืืคืงืืื ืืืช ืืื ืืืื ืืืฉืจ ื ืจืฆื ืืืืื ืคืจืืืจ ืจืง ืคืขื ืืืช ืืืงืจื ืืื thread_num ืืื ืืคืจืืืจ ืืื.
ืื ื ืืืืง ืืช ืชืืฆืืืช ืืืจืฆืื ืขืืืจ ืืขืจืืื ืืืืืื ืืืืืื ื ืงืื

ืืืืืจ ืื ืื ื ืจืืืื ืฉืืื ื ืืืจืฆื ืืืงืืืืืื ืืจืืขืื ืืืชืจ ืืืกืืจืชืืื.
ืื ืืืื ืื ืืืข ืืืื ืกืืืืช:
1) overhead
2) cache- ืืื thread ืฉืจืฅ ืขื ืืขืื ืืืจ ืืฉ L1 cache ืืฉืื. ื ืืืืจ ืฉืืืฉืจ ืงืืจืืื ืืืืข ืืืืืจืื ืืฉืืื ื cache ืฉืืื ืื ืืช ืืืืืข ืืกืืื ืืืืชื cache line ืืื ืืฉืืืจ ืขื ืืืงืืืืช ืืืืื. ืืชืื ืืช ืืงืืืื multicore ืืืฉืจ thread ืืฉื ื ืืช ืcache ืืืขืื ืฉืื, ืืืืืจื ืืืืืขื ืืฉืืจ ืืืขืืืื ืฉืcache ืืฉืชื ื ืืืชืจืืฉ cache invalidation ืื ืฉืืืจื ืืื L1 cache ืฉื ืthreads ืืืฉืช ืฉืื ืRAM ืขื ืื ืคืขืืืช ืืืืืจ ืื ืฉืืืฆืจ ืืืกืจ ื ืืฆืื ืฉื ืcache .
ืื ืืคืชืจืื?
ื ืืื ืืฉื ืืช ืืช Partial sum ืืขืืืจ ืขื ืืขืจื ืื ืืืืื ืืื threads ืืงืื ืฉืืจื ืืฉืื ืืืื ืื ืืืื ืืฆื ืฉthreads ืืืจืกืื ืืช ืlines ืืื ืฉื ืืฉื ื.

ื ืืชื ืืจืืืช ืฉืื ืืื ืืฉืคืจ ืืฉืืขืืชืืช ืืช ืืืืฆืืขืื ืฉื ืชืืื ืืช ืืงืืืืืช

ืื ืื ื ืืืืขืื ืฉืืชืงืืื
ืืืืืจ ื ืืื ืืงืื ืงืืจืื ืฉื

ื ืืชืื ืงืื ืืงืืืื ืฉืืืคืฉืจ ืื ื ืืืฉื ืืช ืื ืื ืืื ืืช ืืืืฆืืขืื ืฉืื ืืขืืืช ืงืื ืกืืจืชื
ืืืืฉืื ืืืงืืืื ืืืื ืืืื ืืื ืฉืขืฉืื ื ืืืืืืืืช ืืงืืืืืช, ืื thread ืืืฆืข ืกืืื ืืืงื ืฉื ืฉืืื ืืืืื ืื ืืืืกืืฃ ืืงืืข ืงืื ืกืืจืชื ืืกืืื ืืช ืื ืืกืืืืื ืืืืงืืื. ืืช ืืกืืืืื ื ืืชื ืืฉืืืจ ืืืืฆืขืืช ืืขืจื ืฉืืืืื ืืืกืคืจ ืthreads ืืืื ืื thread ืืงืื ืืฉืืฆืช ืืืช ืืืขืจื ืืืื ืืืืื ืrace condition (ืืคื ืฉืืจืื ื, ืื ืืืื ืืคืืืข ืืืืฆืืขืื ืื ืื ืืืงืืื ืืืฉืืื ืืช ืืืืืื).

ืืชืื ืืช ืืงืืืื ืื ืืืจืื ืืื
#include <omp.h>
#include<stdio.h>
#define N 2 // required number of threadsint main ()
int N_actual; // actual number of threads
ย ย long num_steps = 100000;
ย ย double sum[N] = {0};
ย ย double step = 1.0/(double) num_steps;
omp_set_num_threads(N);
#pragma omp parallel
{
int id = omp_get_thread_num();
double x;
#pragma omp single
N_actual = omp_get_num_threads();
ย ย for (int i=id; i< num_steps; i+= N_actual) {
ย ย ย ย x = (i+0.5)*step;
ย ย ย ย sum[id] += 4.0/(1.0+x*x);
ย ย }
}
ย ย double pi = 0;
for (int i=0; i < N_actual; i++)
pi += step * sum[i];
ย ย printf("%f\n", pi);
ย ย return 0;
}
ืื ื ืืืื ืืืฆืืขืื ื ืงืื

ื ืืชื ืืจืืืช ืฉืืื ื N=3 ืืฉ ืืจืืืช ืืืฆืืขืื. ืืกืืื ืืื ืืื ืืืืืื ืฉืืืขืื ืืื ืืฉ ืืื ืืืืืช ืืืื ืืืื ื ืืชื ืืืจืืฅ ืืกืคืจ HW threads (ืืืดื 2) ืืืื ืืคืชืจืื ืืช ืืืืืจืชืืื ืฉืืฉ ืืืขืืืื ืืจืืื ืืืืืช ืืื ืฉืืจืืข ืฉืืฉ ืฉื ื cores ืขื ืืืชื ืชืืื ืืช ืื L1 cache ืฉื ืืื ืืื ืืฉืชื ื , ืืื ืืืืืข ืL1 cache ืฉื ืืืืจืื ืฉืื invalid ืืขืืืื ืืขืืื ืืช ืืืืืื ืฉืืื.
ื ืืงื ืืืฆืืข ืฉื ืืจืืขื threads . ืืืืืื ืฉืื core ืืืื ืฉื ื HR (Hardware threads), ืืื ืืืื ืืืจืืฅ ืฉื ื threads. ืืจืืขื threads ืืจืืฆื ืขื ืฉื ื cores ืฉืื ืื. ืืื core ืืฉ L1 cache ืคืจืื ืืฉืื. ืืืฉืจ thread0 ืจืืฆื ืืขืืื

ืืืฉืจ thread2 ืจืืฆื ืืขืืื

ืืคืชืจืื ืืื ืืงืฆืื ืฉื ืืขืจื ืื ืืืืื ืฉืชืื ืข ืืคืืคื ืืื cache lines ืฉื threads ืฉืื ืื. ืืืื ื, ืื ืืืืื ืืืจืื RAM, ืืื ืืืจืื ืืื ืืื ืืฉื ื ืืขืืืช ืืื ืจืืฆื.
#include <omp.h>
#include<stdio.h>
#define N 2 // required number of threads
#define PAD 8 // assume 64-byte L1 cache line size
int main () {
int N_actual; // actual number of threads
ย ย long num_steps = 100000000;
ย ย double sum[N][PAD] = 0;
ย ย double step = 1.0/(double) num_steps;
double tdata = omp_get_wtime();
omp_set_num_threads(N);
#pragma omp parallel
{
int id = omp_get_thread_num();
double x;
#pragma omp single
N_actual = omp_get_num_threads();
ย ย for (int i=id; i< num_steps; i+= N_actual) {
ย ย ย ย x = (i+0.5)*step;
ย ย ย ย sum[id][0] += 4.0/(1.0+x*x);
ย ย }
}
ย ย double pi = 0;
for (int i=0; i < N_actual; i++)
pi += step * sum[i][PAD];
tdata = omp_get_wtime() - tdata;
printf("pi = %f in %f secs\n", pi, tdata);
ย ย return 0;
}
ืืืืื ืฉืื thread ืขืืื ืขื ืฉืืจื ืฉืื ืืืขืจื ืืืชืื ื id, ืืื ืืื ืฉืืจืืช cache ืืฉืืชืคืืช.

ืืืื ืจืืฆื ืืื ืืฉืชืคืจ ืื ืขืืืจ N=3,4. ืืืืืจ ืฉืงืืืื ื ืืื ืงืื ืืืื ืืกืืจืื. ื ื ืกื ืืืืื ืืจืืื ื ืืกืคืืช.
ืืื ื ืืกืฃ ืืื ืืืืจืช critical section ืืชืื ืืงืื ืืืงืืืื , ืืืงืื ืืืืืืง ืืขืจื ืฉื ืกืืืืื ืืืงืืื ื ืืื ืืืืื ืฉืื thread ืืืฉื ืืช ืืกืืื ืฉืื ืืฆืืจื ืืงืืืืช ืืืงืืข ืืงืื ืืงืจืืื ื ืกืืื ืืช ืืชืืฆืื ืืกืืคืืช ืืขืจื ืฉื
#include <omp.h>
#include<stdio.h>
#define N 2 // required number of threadsint main () {
ย ย long num_steps = 100000000;
ย ย double pi = 0;
ย ย double step = 1.0/(double) num_steps;
double tdata = omp_get_wtime();
omp_set_num_threads(N);
#pragma omp parallel
{
int id = omp_get_thread_num();
double x, sum = 0;
#pragma omp single
N_actual = omp_get_num_threads();
ย ย for (int i=id; i< num_steps; i+= N_actual) {
ย ย ย ย x = (i+0.5)*step;
sum += 4.0/(1.0+x*x);
}
ย ย ย ย #pragma omp critical
pi += sum * step;
}
tdata = omp_get_wtime() - tdata;
printf("pi = %f in %f secs\n", pi, tdata);
ย ย return 0;
}
ืืฉืืื ืื ื ืงืื ืืืฆืืขืื ืืืืื ืืฉืืื ืืงืืืืช ืืงืื ืืืชืจ ืืกืืืจ.
ืืื ืืืื ืืืืืืช ืืฉืืืื ื OpenMP:
#include <omp.h>
#include<stdio.h>
int main () {
#pragma omp parallel
{
for(int i=0; i<2; i++)
printf("i=%d, ID=%d\n", i, omp_get_thread_num());
}
return 0;
}
#include <omp.h>
#include<stdio.h>
int main () {
#pragma omp parallel
{
#pragma omp for
for(int i=0; i<2; i++)
printf("i=%d, ID=%d\n", i, omp_get_thread_num());
}
return 0;
}
//or use:
int main () {
#pragma omp parallel for
for(int i=0; i<2; i++)
printf("i=%d, ID=%d\n", i, omp_get_thread_num());
return 0;
}
ื ืฉืื ืื ืฉืืืืืืช ืืงืื ืืืืจืื ื ืงืื 2 threads ืืื 4 ืืื ืืจืื ืืืงืจืื ืืืืคืืืืื ืืืื ืฉืืงืืืคืืืืจ ืืฉืืชืืฃ ืขื ืืขืจืืช ืืืคืขืื ืืืืืื ืืืงืฆืืช ืคืืืช ืืื ืฉืืื ืืืื ืื ืืกืคืจ ืืืืืจืฆืืืช ืืื 2.
ืืืฉืจ ืืฉ nested loop ืฉืืชืื ืืชืื ืืืืง ืืงืืืื, ืจืง ืืืืืื ืืืืฆืื ืืช ืชืชืืงืื.

ืืืช ืืืชื ืืืืช ืืืืคืืืืืืืช ืื ื ืจืฆื ืืฉื ืืช ืืืชื ื ืืื ืืืฉืชืืฉ ืืืืื ืืฉืืืจื collaps(#loops). ืื ืืืืจ ืืงืืืคืืืืจ ืฉืื ืื ื ืจืืฆืื ืืืงืื ืืช ืื ืืืืืืืช ืืคื ืืืืืช ืขื ืืจืื ืฉืืื ืืืกืคืจ ืฉืืขืืจื ื

ืืืงืจื ืื, ืื thread ืืืฆืข ืืืืจืฆืื ืืืช. ื ืฉืื ืื ืฉืืงืื ืื ืื ืืืื ืืงืืื ืื ืคืืขื ื ืืจืืช ืืืงืืืืืืช ืืื ืื ืื ืืื ืืช ืฉื ืืงืื.
End of loop barrier:
ื ืฉืื ืื ืฉืืฉ barrier ืื ืืคืืจืฉ ืืกืืฃ ืืืืืช for ืืงืืืืืช. ืืืืืจ threads ืืืื ืืกืืฃ ืืืืืื ืืฉืืจ ืthreads ืฉืจืฆืื ืฉืืกืืืื ืืช ืืืืืื ืื ืื.

ื ืืชื ืืจืืืช ืืคื ืืืืคืกื ืฉืื ืthreads ืืืื ืขื ืฉืืืื ืืกืืืื ืืช ืืืืืื ืืจืง ืื ืืชืืืื ืืืืคืกื.
ืื ื ืจืฆื ืืืืจืื ืืช ืืืืืืงื ืืืืช, ื ืืื ืืืืกืืฃ ืืช ืืืืช ืืืคืชื ืืื ืืฆืืจืช ืparallel for ืฉื ืงืจื nowait. ืืจืืข ืฉืืืกืืคืื ืืช ืืืืื ืืื ืื ืืงืืืคืืืจ ืื ืืฆืื ืืืกืื ืกืืื ืืืื ืฉืืฆืืจื ื (ืื ืืฉ ืขืื ืืฆืืจืืช ืืืืฉื ืื ืฉื ืื ืืืืื ืืืืกืื).

ื ืกืชืื ืขื ืืงืื ืืื
#include <omp.h>
#include<stdio.h>
int main () {
int sum = 0;
#pragma omp parallel
{
#pragma omp for reduction (+:sum)
for(int i=0; i<10; i++) {
sum += i;
printf("thread%d sum = %d\n",
omp_get_thread_num(), sum);
}
}
printf("sum = %d\n", sum);
return 0;
}
ื ื ืกื ืืืืื ืื ืงืืจื ืืื ืขื ืืื ืืชืืื ื ืืช ืืืืคืกืืช

ืื ืื, ืืื ืืืื reduction?
ืืืื ืืื ืืงืื ืืื ืกืืืจ ืืืฆืืจื
ืืื ืื ืืคืขืืืืช ืืืคืฉืจืืืช ืืขืจื ืืืชืืื ืขืืืจื-

ื ืจืื ืืขืช ืืืฆื ืืืงืื ืืช ืงืื ื Pi Approximation ืืืงืืื ืืืืฆืขืืช reduction

ืืขืช ื ืืชื ืืจืืืช ืืื ืืืืืืฉ ืืืื ื ืงื ืืืฉืื ื ืืช ืืงืืจืื ืฉื
Reduction with Arrays:

ื ืืชื ืืืฆืข reductio ืื ืขื ืืขืจืืื ืืืืืฆืจ ืฉืืคืื ืฉืืื ืืื thread.
ื ืกืชืื ืขื ืงืืข ืืงืื ืืื

ืืืืืื ืืืืฆืื ืืช ืืชืืืงืช ืฉืืื (ืืืืก ืืืกืคืจ ืืืืืจืฆืืืช) ืืื ืืจืืขืช ืthreads ืฉื ืืฆืจื.
ืืืืืื ืืคื ืืืืช ืืื ืืงืืืืช ืืื threads ืืคื ืฉืืืจื ื.
ื ืฉืื ืื ืฉืืืื ื ืืืืืงื ืฉื ืืกืคืจ ืืืืืจืฆืืืช ืฉืืื, ืืื ืื ืืื ืืthreads ืืจืืฅ ืืจืืฅ ืขื ืขืจืื i ืฉืื ืื. ืืื ืชืืื ืคื ืืขืื ืฉthreads ืฉืืงืืืื ืืช 3 ืืืืืจืฆืืืช ืืืืืืืช ืืืชืจ ืืืฆืขื ืืืชืจ ืคืขืืืืช ืืืฉืืืืืช ืืืืคื ืืืืจืช ืืืืืื ืืคื ืืืืช.

ืืืืืืื ืฉื ืืืืืื ืืืืช ืคืืข ื load balance ืฉืื ืืขืืืื ืื ืืชืืืงืช ืฉืืื ืืฉืืื.
ืืื ืืืคื ืืื ื ืฉืชืืฉ ืkey work ืฉื ืงืจื schedule. ืืืืื ืืฉืืืจื ืืื ืืงืื ืืคืจืืืจ ืืช ืืืคื ืืืงืฆืื (static ืื dynamic ืืืฉ ืื ื ืืกืคืื) ืืคืจืืืจ ื ืืกืฃ ืฉืืื ืืกืคืจ ืฉืงืืืข ืดืืื ืืืืจืฆืืืช ื ืจืฆื ืืืงืฆืืช ืืื thread ืขืืืจ ืจืืฆื ืืืช ืืคื ื ืฉืืื ืดืืืืืฃืด ืthread ืืื.

ืืืฉืจ ื ืฉืื 1 ืืงืื ืื ืดื ื ืงืื ืืชื ืืืืช ืฉืืืืืจื Round Robin, ืื thread ืืจืืฅ ืืืืจืฆืื ืืืช ืืื ืthread ืืื ืืจืืฅ ืืช ืืืืืจืฆืื ืืืื ืืชืืจ ืืื ืืืื.

ืื ืืืื ื ืืืืืืื ืืช ืืคืจืืืจ ื 1 ื 2 ืืืื ื ืืงืืืื load balance ืคืืืช ืืื:

ืืื ืืืืช ืชืฉืืื ื ืืื ื ืืงืืืขืช ืืืื chunk ืืชืืื ืื ืืฉืื ืืฆืืื ืฉืฉืืืืฉ ื static scheduling ืืื ืืืื ืืขืื ืื ืืื ืฆืืจื ืืืื ืืชืงืฉืืจืช ืืื ืthreads ืฉืื ืืืื ืืจืืฆื ืื ืืื ืืืืข ืืืืืืง ืื ืขืืื ืืืจืืฅ ืืืื ืืืืจืฆืืืช.
ืืืืงื ืกืืืืช ืืืืื ืืืืืช ืื ืืืฆืืืช ืืืฉืจ ืื ื ืืชื ืืืขืช ืืจืืฉ ืืื ืืืฉืืืื ืืฉ ืืื ืืืืจืฆืื ืืืฉื ืื ืืงืื ืืืขืื ืืืื ื ืืืืืจืื ืืืงืื ืืจืืฅ ืขื i ืืจืืฅ ืขื rand ืืืื ื ืืืืืื ืืงืื ืืืืงื ืื ืฉืืืืืื ืืช ืฉืคืืืขืช ื balance.

ืืืงืจืื ืืื ืื ืดื ื ืืชื ืืืืืืจ ืื ืฉืืืืืงื ืชืืื dynamic.
ืืืฆื ืื ืื thread ืืงืื chunk ืฉื ืืืืจืฆืืืช ืืคื ืืคืจืืืจ ืฉืืืืจื ื ืืืกืคืจ ืืืืืจืฆืืืช ืืืืืื ืืืืฆืื ืืช ืืืืฆืข ืืืชื ืืื ืืื ืืืืง ืืช ืืขืืืื ืืฆืืจื ืืื ืืืช ืืื ืืืืจื ืกืืจ ืกืคืฆืืคื ืืื ืขื ืืืืืจืืชื ืฉืืืืืจ Thread Pool.
int main()
{
#pragma omp parallel for schedule(dynamic, 1)
for (int i = 0; i < 20; i++)
{
printf("Thread %d is running number %d\n",omp_get_thread_num(),i);
}
return 0;
}
ืืคืื ืืืื :
Thread 1 is running number 2
Thread 1 is running number 7
Thread 1 is running number 9
Thread 1 is running number 10
Thread 1 is running number 11
Thread 1 is running number 13
Thread 1 is running number 14
Thread 1 is running number 15
Thread 1 is running number 17
Thread 1 is running number 19
Thread 3 is running number 0
Thread 0 is running number 4
Thread 8 is running number 12
Thread 4 is running number 3
Thread 6 is running number 6
Thread 9 is running number 16
Thread 5 is running number 1
Thread 7 is running number 8
Thread 10 is running number 18
Thread 2 is running number 5
ืืฉืื ืืฆืืื ืฉืืืงืฆืื ืืื ืืืื ืืช ืืฉืืื ืฉืืคืื ืขืืื ืืชืืืื ืืืื ืื ืืื First Come First Serve ืืืืืจ, ืื ืืฉื ื ืืืืจืฆืืืช ืฉืฆืจืื ืืืฆืข ืืืฉ thread ืคื ืื ืฉืืืื ืืงืืช ืืืชื, ืืื ืืืงื ืืืชื.
ืืื ืื, ืืชืืืื ืืืื ืื ืืืืคื ืื ืืื ืืืืืืืื, ืืจืื ืืืชืจ ืืงืจ ืืืกืืื ืื ื ืืจืฉ ืชืงืฉืืจืช ืืื ื threads ืืืืจ ืื ืืืืจืฆืื, ืืื ืื ืืขืืชืื ืฆืจืื ืืืืืืจ ืืช ืchunk size ืฉื thread ืืืฉืื ืืื ืืืื ืฉืืชืืืื ืืื ืืขืื ืงืืคืกื ืฉืืืจื ืฉื ืืกืคืจืืื ืื ืืืืจื ืฉื ืงืื ืชืืืื ืฉืืชืืื ืื ื.
ืืืืืจ ืืฉืชื ืื ืืืืืืจืื ืืืืฅ ืืงืืข ืืืงืืืื ืื shared.
ืืฉืชื ืื ืืืืืืจืื ืืชืื ืงืืข ืืงืืืื ืื private, ืืืืืจ ืื thread ืืงืื ืขืืชืง ืฉื ืืฉืชื ืื ืืื.

ื ืฉืื ืื ืฉืื ืืฉืชื ืื ืกืืืืื ืืชืื ืืืืง ืืงืืืื, ืื shared.
ื ืืชื ืืฉื ืืช ืืช ื ืจืืืช ืืจืืจืช ืืืื ืฉื ืืืฉืชื ืื:

i ืืืคื ืืืืืืื ืืืฉืชื ื ืคืจืื ืืจืืข ืฉืฉืืื ืืืชื ืืชืื parallel for ื j ืืคื ืืคืจืื ืืืื ืฉืืฉืชืืฉื ื ืืืืืจื private(j).
ืืกืืื ืฉืืืืจื ื ืืช ืืืขืจืืื ืstatic ืืื ืฉืื ืืฉืื ื global data segment ืืื ืstack ืืื ื ืื ืข ื seg fault (ืืขืจืืช ืืืคืขืื ืืืืืจื ื stack ืืืื ืงืืืข ืืืคืขืืื ืืื ืื ืชืงืฆื ืขืื ืขืืืจ ืstack , ื ืืชื ืืืืืง ืืช ืืืื ืstack ืืงืืืข ืืื ืชืืื ืืช ืขื ืืื ืืจืฆืช ืืชืืื ืืช ulimit -s).

ื ืฉืื ืื: ืืืฆืืจื private ืืืืฆืจืช ืขืืชืง ืฉื ืืืฉืชื ื ืืืื ื ืืฆืจ ืขืืชืง ืฉื ืืืฉืชื ื ืืชืื ืthreads, ืืขืจื ืฉื ืืขืืชืงืื ืื ืื ืืืื ืืืืื ืืืฉืชื ื ืืืงืืจื ืืืืืจ ืื ืฉืื ืื ืืชืื ืืงืื ืืืงืืืื ืื ืืฉืคืืข ืขื ืืืฉืชื ื ืืืงืืจื. ืืื ืื ืืื ืืืืื ืฉืื ืืขืจื ืฉื ืืืฉืชื ื ืืืงืืจื ืืขืืืจ ืืขืืชืง ืืืฉื:

ืืืื ื ืืขืจื ืืื 1, ืืื ืื ืืื ืืthreads ืงืืื ืขืจื ืืชืืืชื ืฉื 0 ืขืืืจ ืืขืืชืง ืฉื sum.
ืืคืฉืจ ืืืืืืจ ืืฉืชื ื ืืืืืช private ืจืง ืืืืง ืืกืืืื ืืชืื ืืงืื ืืืงืืืื.

ืืืงืจื ืืื ื ืืชื ืืจืืืช ืืื ืืืืจ ืืืฆืืื ืืืืืืื sum ื ืฉืืจ ืขื ืขืจื 1.


ืื ืืขืจื ืฉืืืืคืก ืืื?

ืfirstprivate ืืืืจ ืฉืื ืthreads ืืงืืื ืืช ืืขืจื ืืืชืืืชื ืืขืืชืง ืฉืืื, ืฉืืื 0. ืlastprivate ืืืืจ ืฉื ืฉืื ืsum ืืืืฆืื ื ืืช ืืขืจื ืฉืงืืื ืืกืืื ืืืืงื ืฉื ืthread ืืืืจืื. ืืืืื ืฉืืืืคืืื ืืืืืจ ืื ืืืื ืกืืื ืืื ืืืืืงื ืืื ืื ืฉืืื (ืืฉ 9 ืืืืจืฆืืืช ืขื 4 threads) ืื ื ืืชื ืืืืืช ืืช ืืชืืฆืื ืืจืืฉ. ื ื ืื ืฉ thread0 ืืงืื ืืช 3 ืืืืืจืฆืืืช ืืจืืฉืื ืืช ืื ืืื ืืช ืืืืคืกืืช

ื ืืชื ืืจืืืช ืฉืืืืื ืฉ ID3 ืงืืื ืจืง ืืช 2 ืืืืืจืฆืืืช ืืืืจืื ืืช ืื ืืื ืืกืืื ืืช ืืกืืื ืืืืงื ืฉ i=8,9 ืืืื ืืคืื ืืืื 17.
ืืจืื ืืืืืฅ ืืื ืืืฉืชืืฉ ืืืืืช ืืืคืชื default(none) ืืื ืืงืื ืืืืงืช ืงืืืคืืืฆืื ืฉืืืจืืื ืืืชื ื ืืจืฉืื ืขืืืจ ืื ืืฉืชื ื, ืืื ืจืืช ืืฉืืชืืฃ ืฉืื. ืืืจื ืืงืื ืืืืืช ืืืื ืืืชืจ.

ืงืื: ืืกืคืจ ืืืขื n
ืคืื: ืื ืืืกืคืจืื ืืจืืฉืื ืืื ื 1 ืขื ื n.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void calcPrimes(int n) {
bool *prime = (bool *)malloc((n + 1) * sizeof(bool));
if (prime == NULL) {
printf("Memory allocation failed.\n");
return;
}
// Initialize all elements of prime[] as true
#pragma omp parallel for
for (int i = 0; i <= n; i++)
prime[i] = true;
// Mark non-prime numbers
#pragma omp parallel for schedule(dynamic, 1)
for (int p = 2; p * p <= n; p++) {
for(int d = 2; d<p && prime[p]; d++)
if(p % d == 0)
prime[p] = false;
}
// Print prime numbers
printf("Prime numbers in the range 2 to %d are:\n", n);
for (int p = 2; p <= n; p++) {
if (prime[p])
printf("%d ", p);
}
printf("\n");
free(prime);
}
ืจืืื ื ืืืจ ืืจื ืืืฉื bfs ืืงืืืื ืขื pthreads. ืืขืช ื ืจืื ืืืฆื ื ืืชื ืืืฉื ืืช ืื ืืฆืืจื ืืงืืืืืช ืขื OpenMP.
SEQUENTIAL_BFS(V, E, s)
#pragma openmp parallel for
for each ๐ฃโ๐
๐๐๐๐๐_๐ฃโ๐คโ๐๐ก๐
๐_๐ฃโโ
๐_๐ฃโโ
๐๐๐๐๐_๐ โ๐๐๐๐ฆ
๐_๐ โ0
define queue ๐โ{๐ }
while ๐โ โ
๐ฃโ๐.๐๐๐๐ข๐๐ข๐( )
๐๐๐๐๐_๐ฃโ๐๐๐๐๐
#pragma openmp parallel for
for each ๐ข adjacent to ๐ฃ
if ๐๐๐๐๐_๐ข is ๐คโ๐๐ก๐
#pragma omp critical
๐.๐๐๐๐ข๐๐ข๐(๐ข)
๐๐๐๐๐_๐ขโ๐๐๐๐ฆ
๐_๐ขโ๐ฃ
๐_๐ขโ๐_๐ฃ+1
ืืฉืืื ืืืืช ืืื ืืขืืืชืืช ืืคื ืฉืืืจื ื ืืฉ ืฆืืจื ืืืืืืจ ืชืืจ ืืื ืฉืืื ืขื ืื ืช ืืืื ืข ืrace condition ืฉืขืืื ืืืจืื ืืืืืืจืืชื ืืืฆืื ืืกืืื ืืจืื ืืืชืจ ืืืืกืืื ืืงืฆืจ ืืืืชืจ ืดืืืขืืชืด.
ื OpenMP ื ืืื ืืืฆืืจ ืชืืจ ืืื ืจืื ืขื ืฉื ื ืชืืจืื ืืืื.
SEQUENTIAL_BFS(V, E, s)
#pragma openmp parallel for
for each ๐ฃโ๐
๐๐๐๐๐_๐ฃโ๐คโ๐๐ก๐
๐_๐ฃโโ
๐_๐ฃโโ
๐๐๐๐๐_๐ โ๐๐๐๐ฆ
๐_๐ โ0
define queue ๐1โ{๐ }
define queue ๐2โ{ }
while ๐1โ โ
#pragma openmp parallel for
for each v in Q1
๐๐๐๐๐_๐ฃโ๐๐๐๐๐
#pragma openmp parallel for
for each ๐ข adjacent to ๐ฃ
if ๐๐๐๐๐_๐ข is ๐คโ๐๐ก๐
#pragma omp critical
๐2.๐๐๐๐ข๐๐ข๐(๐ข)
๐๐๐๐๐_๐ขโ๐๐๐๐ฆ
๐_๐ขโ๐ฃ
๐_๐ขโ๐_๐ฃ+1
empty Q1
swap Q1 and Q2
ืืืฉื ืฉืืืฆื ืDirection Optimizing BFS ืืฆืืื ืืืฉื ืฉืืชืืืื ืืืชืจ ืืชืื ืืช ืืงืืืื. ืืืืฉื ืืืืช ืืืืจืช ืฉื ืืืืง ืืขืจื ืฉื frontier ืืืื ืืืืจืฆืื bottom-up ืืืงืื ืืจืืฅ ืขื ืื ืืฉืื ืื ืฉื ืงืืืงืื
ืืกืืื ืฉืืฆืืจื ืืืงืืืืืช ืืฉืืื ืืืืช ืืืชืจ ืืขืืื ืืื ืืืื ืฉืื ืื ื ืืื ืขืื Race conditions ืจืืื ืืืืจ ืืขืืืื ืฉืื thread ื ืืืฉ ืืืขืจื parent ืืืื ืืงืก ืฉืืืืื ืขื ืืงืืืงืื ืฉืขืืื ืืื ืขืืื. ื ืืื ืื ืืืื ืข ืืกื ืืื ืฉื ืงืืืฆืช ื next ื ืืื ืืืืฉ ืืช ืื ืืืืฆืขืืช ืืขืจื ืขืืืงืื ืืืื ืื thread ื ืืืฉ ืจืง ืืืชืืืช ืืืชืืืื ืืงืืืงืื ืืืชืืื ืขืืืจื.
ืืืืืืจืืชื bottom-up ืืฆืืจื ืกืืจืชืืช ืืจืื ืคืืืช ืืื ืืืืืฉื ืืจืืืื ืฉืื ืื ื ืืืืจืื.
ืืืืืืฉ ืืกืืจืชื ื ืจืื ืื:


ืืฆืืจื ืืงืืืืืช , ื ืืื ืืืชืื ืืขืจื ืparents ืืฆืืจื ืืงืืืืืช ืืื ืืฆืืจื ืืื ืืืช ืืจืืฅ ืขื ืื ืืงืืืงืืืื (ืืกืืื ืฉืืฆืืจื ืืื ืืื ืืืช ืืื ืืืื ืฉืื ืื ื ืื ืืืืขืื ืืืื ืงืืืงืืืื ืื ืขื ืืืชืจ ืฉืื ืื ืืืืื ืขื ืคืืืช). ืืืืืื ืืฉื ืืื ืืืจ ืืืืื ืืืืืช ืกืืืืช ืฉืื ืืืืช ืืขืืืื ืืื ืฉืืื ืืื ืืืืจืฆืื ืคื ืืืืช. ืืื ืื ื ืฉืื ืื ืฉืืื ืืื ืืืื ืกื ืืจืื ืคืจื ืืกื ืืจืื ืืืืคืืืื, ืืืงืื ืฉื ืขืืื ืขื ืฉื ื ืชืืจืื ืขื counter ืฉืืืคื ืืืืืช 0 ืจืง ืืืฉืจ ื bottom-up ืื ืืืฆื ืฉืื ืงืืืงืื ืฉืืืืจื ืฉืื ืดืื ืงืืืืด ืืืขืจื ืparent.

ื ืจืื ืงืื c ืฉืืืฉ DFS ืืงืืืื ืืืืฆืขืืช OMP:
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#define MAX_NODES 100
int graph[MAX_NODES][MAX_NODES];
int num_nodes;
enum colors {NOT_VISITED, VISIT_IS_IN_TASK_QUEUE, ALREADY_VISITED};
enum colors visited[MAX_NODES];
void parallel_dfs_visit(int node) {
visited[node] = ALREADY_VISITED;
printf("Node %d is visited by thread %d\n", node, omp_get_thread_num());
for (int i = 0; i < num_nodes; i++) {
if (graph[node][i]) {
#pragma omp critical
{
if (visited[i] == NOT_VISITED) {
printf("thread %d: create task for node %d\n", omp_get_thread_num(),i);
visited[i] = VISIT_IS_IN_TASK_QUEUE;
#pragma omp task
parallel_dfs_visit(i);
}
}
}
}
}
void dfs() {
for (int i = 0; i < num_nodes; i++) {
printf("thread %d: examine node %d\n", omp_get_thread_num(), i);
if (visited[i] == NOT_VISITED) {
printf("\nstarting DFS visit from %d\n", i);
#pragma omp parallel
{
#pragma omp single
{
parallel_dfs_visit(i);
}
}
} else if (visited[i] == VISIT_IS_IN_TASK_QUEUE) {
perror("error: VISIT_IS_IN_TASK_QUEUE shouldn't be possible here\n");
}
}
}
ืืงืื ืืื ืืก thread ืืื ืืชืื ื dfs_visit ืืืื ืื ืคืขื ืืืกืืฃ task ืืคืื ืงืฆืืืช ืvisit ืืืงืืืืืช. ืืื ืืขืฆื ืื ืื ื ืืืฆืขืื ืกืจืืงื ืขืืืง ืืื ืื ืืฉืื ืื ืฉื ืงืืืงืื ืืืฉืื ืขืืฉืื ืืช ืื ืืงืืืื (ืงืฆืช ืขืืืืช ืฉื DFS ืฉืืฉืื ืืชืืื BFS). ืฆืจืื ืืฉืื ืื ืฉืื ืขื ืืขืืืืช ืืื ืืืืืจ BFS , ืืืืืจ ืืืื ื ืืืืืื ืืืื ืืื ืืช ืื ืื ืื ืืืืกืก priorities ืฉื ืืชื ื task ืืช ืืขืืืคืืช ืฉื ืืจืื ืฉื ืืืชื ืงืืืงืื ืืืจืฃ. ืืื ืขืืืื ืื ืื ืืื BFS ืืืฉืื ืฉืื ืืืื ืืืืืช ืืฆืืื ืฉืtask queue ืืงืฆื ืืฉืืืืช ืขื ืขืืืง ื ืืื ืืืชืจ ืื ืืฉ threads ืืืืืืจ, ืืคื ื ืฉืื ืืจืื ืืกืชืืืื.
ืืคืฉืจ ืืืืื ื task ืขืจื ืฉื priority ืืขืช ืืืฆืืจื ืฉืื ืขื task priority(#p) ื pragma block.
ืืืืืืฉ ืื ืดื ืืื ื ืืืฉืื ืฉืื ืืื ื ืืขื ืืชDFS visit ืขื critical block , ืืฉ ืืื ืืฉืคืขืืช ืฉื ืคืืืขื ืืืงืืืืืืช ืขืืืื ื ืืืจ ืืืืฉื
ืืขืืืช producer/consumer ืืืืืจืช ืืืืคื ืืื. ืืฉ ืื ื bounded buffer ืืืืื N ืชืืื. producer ืืืืฆืจ items ืืฉื ืืืชื ื- buffer ืืืงืื ืคื ืื. consumer ืฆืืจื items ืืืคื ื ืืงืื ื- buffer. ืขื consumer ืืืืืช ืืื ืฉ- item ืืื ืก ื- buffer ืืคื ื ืฉืืืื ืืฆืจืื ืืืชื, ืืขื producer ืืืืืช ืขื ืฉืืืื ืืงืื ืคื ืื ื- buffer ืืื ืฉืืืื ืืฉืื ืฉื item ืืืฉ.
ืงืื ืกืืจืชื ืืจืื ืืืฆืืจื ืฉืื ืืื ืืืืจืฆืื ื ืืฆืจ item ืืื, ืืืื ืืื ื ืฆืจื.

ืืื ืืืคืื ืืืชื ืืชืืื ืืช ืืงืืืืืช ืืื ืฉ- producer ื- consumer ืืืืื ืืขืืื ืื ืืื ืื ืคืจื ืืืืงืืื ? ืขื ืืืืื ืฉืืืื ื ื OpenMP ืขื ืื, ื ืจืื ืฉืื ืงืืื ืืื ืฉืืขืืืจ ืื ื ืฉืื ืื ืื ื ืื ืจืืฆืื ืืืืง ืืฉืืื ืืืืงืื ืืื ืืืืืืจ ืฉืชื ืืฉืืืืช ืฉืื ืืช ืขืืืจ ืื thread. ืื ืืขืื ืฉืื ื ืชืงืื ื ืื ืขื ืื ืื ืื ืื ื ืจืืฆืื ืืืืง ืชืคืงืืืื ืืื ืืืืจืฆืืืช.

ืืืื ืืืืืืจ ื ืงืจื sections:

ืืงืื ืื ืดื ืืฉื ื ืืขืื, ืืคืื ืขืืื ืืืืืช ืฉืื ื ืืื ืจืืฆื ืืืืืื ืฉืฉื ื threads ืขืืืืื ืืขืืื ืขื ืฉื ื ืืขืืืื ืฉืื ืื ืืืื ืืขืืืื ืฉื
ืืื ืืืคื ืืืขืื ืืืืช ื ืืชื ืืืฉืชืืฉ ืืคืื ืงืฆืื flush

ืืคืื ืงืฆืื ืืืืช ืืขืฆื ืืืจืืื ืืช ืืืืืข ืืืชืขืืื ืื ืram ืืื ืจืง ื cache. ื ืฉืื ืื ืฉืื ืื ืืืฆื ืฉื cache invalidation ืฉืืืืจื ื ืขืืื ืงืืื, ืืฆื ืฉื cache invalidation ืืืจื ืืืขืื ื ืฉื ืืืืืข ืืRAM ืืื ืืขืืืื ืืืืืข ืRAM.
ืืื ื ืืืื ืืช ืืืื ืืช ืืืืืข ื cache, ืืื ืขืืืื ืืคืื ืขืืื ืืืืืช ืฉืื ื ืืื ืืจืฆื ืืืื ืฉืืืื ืืืืืช ืืฆื ืฉืืคื ื ืฉื ืืืข ื flush ืืืืจืื ืขืืืจ flags ืืชืขืืื ืืื ืขืืืจ ืืืขืจื ืื, ืืื ืconsumer ืืฆื ืืbusy wait ืฉืื (ืืืืืช ื while) ืืืกืืื ืขืจื ืื ืขืืื ื.
ืืคืชืจืื ืืื ืืืืกืืฃ ืขืื flush ืื ืืืจื ืขืืืื ืฉื A ืืื ืืืจื ืขืืืื ืฉื flags

ืฆืจืื ืืฉืื ืื ืฉืืืืืื ืืืจืืช ืืคืขืืื ืืืืช ืืืืจืช ืืืืืืช ืื ืืขืืื ืขื ืcache ืืืื ืืื ืจืง ืขื RAM ืืืื ืืืช ืคืขืืื ืืืื ืืงืจื ืืืืงืืช ืืื ืจื.
ื ืืื ืืืฆืืืจ ืขื nested section ืืชืื section ืงืืื. ืืื nested for , ื nested section ืืืืคื ืืืคืืืื ืจืฆืื ืืฆืืจื ืกืืจืชืืช ืขื ืืื ืthread ืฉืืจืืฅ ืืช ืsection ืื.

ืื ื ืจืฆื ืืฉื ืืช ืืช ืืืชื ืืืืช ืืืืช ื ืฉืชืืฉ ื omp_set_nested(1) ืืืืฅ ื pragma block ืืื ืืืคืฉืจ ืืงืืืืืืช ืืงืื ื ืช.
ื ืจืฆื ืืืจืืืช ืืืฆื ืืืฉืชืืฉ ื OpenMP ืืื ืืืงืื ืืช ืืงืื ืืื

ืืืฆืขื ืืืื ืืืืืืืืืช ืืื ืืืงืื ืืืืืช while , ืืืจ ืฉืื ืืชืืคืฉืจ ื default ืืื ืืืืืจ ืืช ืืจืฉืืื ืืืงืืฉืจืช ืืืขืจื ืืื ืขื ืื ืืจืืฅ ืืฆืืจื ืืงืืืืืช.

ืืฉ ืคื overhead ืฉื ืืขืชืงื. ืืืฉืชืืฉ ื sections ืืื ืื ืืขืืืชื ืื ืื ืื ื ืื ืืืืืื ืืืขืช ืืื ืืกืคืจ ืsections ืฉื ืจืฆื ืืืืฆืจ. ื ืจืฆื ืืื ืฉืืชืืื ืืืงืืื ืฉื ืืฆื ืืื ืฉืื ืื ืืืืข ืืื tasks ื ืจืฆื ืืืืฆืจ, ืืืื ืืื ื ืงืจื Tasks.
ื ืกืชืื ืขื ืืกืื ืชืงืก:

ืืืืื ืืืืืชื ืืื tasks ื sections ืืื ืฉืืื ืืฉ task queue ืฉืื ืื ืืช ืืืฉืืืืช. ืืชืื ืืงืื ืืืงืืืื ืขืืคื ื ืืช ืืชืืื ืืช ืืงืื single ืืื ืฉืจืง thread ืืื ืืืฆืจ ืืช ืtasks ืืืื ืืก ืืืชื ื task pool.
ืืื ืืฉ ืคื ืืืืืฉ ืืืื ืืืื ืThread Pool , ื threads ืฉืืืคืื ืืฉืืืืช ืืtask queue ืื ืขืื ืื ืืืืืื.

ืขืืืจ ืืชืืื ืืช ืื ืดื ืืคืื ืืืื

ืืืจืฆื ืืื ืจืืืื ืฉ- thread2 ืืกืคืืง ืืืฆืข 3 tasks, ืืื ืฉืืจ ื- threads ืจืง task ืืื. ืื ืชืืื ืืชืืืื ืฉื threads ืืืืจืืืืืช ืฉื tasks ืื ืื ืฉืื ืื.
ื ืืชื ืื ืืืืืืจ explicit barriers ื tasks ืืืืืจ, ื ืืชื ืืืืืช ืืืกืคืจ tasks ืฉืืกืชืืืื ืืคื ื ืฉืืื ืืกืื tasks ืืืฉืื:

ืื ื ืจืฆื ืืืืฉ ืืช ืื ืขื ืlinked list ืฉืื ื ื ืจืฆื ืืืืื ืื ืืืืืืืช ืฉืื ื ืืชื ืืืื ืข ืืื ืืื ืื ืื ื ืืืืืื ืืขืฉืืช.
ืื ืื ืืืืื ืืืจืื ืืืฆืืจื

ืืงืื ืืืื ืคืฉืื ืืืจืื ืื:

ืืืืืื- thread ืืื ืืื ืืก ืืช ืtasks , ืื task ืืื ืืคืขืืื process ืขื ืืืืจ ืืืฉืื ืืจืฉืืื. ืฉืืจ ื threads ืฉืืืคืื ืืช ืtasks ืืืืฆืขืื ืืืชื ืืงืืืื.
ืคืืืื ืืฆืณื ืืคืจื ืืืฉืื ืืื ืืืืืจืืชื ืฉืคืืชืจ ืืช ืคืืืณ ืืืื
ืื ืื ื ืืืืจืื ืื ืืืืืจืืชื ืคืฉืื ืืืชืจ ืฉืคืืชืจ ืืฆืืจื ืจืืงืืจืกืืืืช ืืืื ืืืื ืืืื

ืื ื ืจืฆื ืืืงืื ืืช ืื ื ืืื ืืืฉืื ืขื ืืืื ืืก ืื ืงืจืืื ืจืงืืจืกืืืืช ื task.

ืืชืืื ืืช ืืืืช ืืืื ืื ืืขืืื ืฉืื ืื ืื ื ืืฉืงืืขืื ืืืื ืืื ืืืงืื ืืืฆืืจืช

ื ืืื ืืืืืืจ ืงืื ืฉืืืงืจ ืืช ืืืืช ืtasks ืืืื ืข ืืtask queue ืืืืื ืืืืช ืืืืื ืืืชืจ ืฉื ืืฉืืืืช ื capacity ืฉื ืืืืจ ืืจืืฉ


ืืงืื ืืื ืืขืฆื ืืืืืจ ืฉืืืจื ืขืืืง ืขืฅ ืจืงืืจืกืื ืฉื 5 ืืงืื ืืขืืืจ ืืืฉื ืืช ืฉืืจ ืืขืืืงืื ืืฆืืจื ืกืืจืชืืช, ืื ืขืืืง ืขืฅ ื ืืื ืืื ืืขืฉื ืืฆืืจื ืืงืืืืืช.
ืืืื ืืฆืืข ื ืจืฆื ืืืื ืข ืืกื ืืจืื ืืื ืืืขืืืช ืจืืช ืืืงืืืืืช.

ืืฉ ืฉื ื ืกืืื ืกื ืืจืื ื openMP:
High level synchronization
Advanced synchronization operations
ืืงืื ืฉืืชืื ืืชืื ordered block ืืืืื ืฉืื ืื ืืจืืฆื ืชืืื ืืงืืืืืช ืืกืืจ ืฉืื ืืงืื ืืืืฆืข ืืืื ืืคื ืืกืืจ ืฉืืื ืืงืื ืืืคืืข ื parallel region ืืืฉื ืืืืืื ืขื ืืืืื
do_some_work(i) {
printf("work% in progressโฆ\n", i)
return i
}
main() {
#pragma omp parallel
{
#pragma omp for ordered
for i = 0 to 4
result = do_some_work(i)
#pragma omp ordered
printf("work%d: %d\n", result)
}
}
ืืคืื ืืืื

ื ืืชื ืืจืืืช ืฉืื ืืืฉืื ื ืขืฉื ืืฆืืจื ืืงืืืืืช ืขื ืืื ืthreads ืืื ืืืืง ืฉื ื ordered ื ืขืฉื ืืคื ืกืืืืจ ืกืืจืชื ืฉื ืืืืืจืฆืืืช.
ืืืืื ื ืืกืคืช ืืืืื ืืืืืช ืขื sections
#pragma omp parallel
{
#pragma omp sections
{
#pragma omp section
{
#pragma omp ordered
printf("Thread %d is executing section 1.\n", omp_get_thread_num());
}
#pragma omp section
{
#pragma omp ordered
printf("Thread %d is executing section 2.\n", omp_get_thread_num());
}
#pragma omp section
{
#pragma omp ordered
printf("Thread %d is executing section 3.\n", omp_get_thread_num());
}
}
}
ืืื ืsections ืจืฆืื ืืืงืืื ืืื ืืืืคืกืืช ืืืื ืืคื ืกืืจ ืืืคืขืชื ืืชืื ื pragma block.

ืืืืจื ื ืขื critical ืืืืืง ืืืืคืฉืจ ืจืง ื thread ืืื ืืืฉืช ืืงืืข ืงืื ืงืจืืื. ืขื ืืืช, ืืฉ ืืื ืืืฉืื ืฉืื ืืืืจื ื ืขืืืื, ืืืฉื, ืื ืื ื ืื ื ืืชื ืฉื ืcritical sections ืฉืื ืืชืื ืืืืืง ืื ืืฉ ืจืง ืื ืขืื ืืื ืฉืืืจืื ืขืืืื ืืืืืจ ืื ื ืขืืชื ืฉืชื ืืืืจื ืงืื ืงืจืืืื ืขื ืืงืื pragma omp critical ืื ืจืง thread ืืื ืืืื ืืืฉืช ืืื ืคืขื ืืืื ืืงืืข ืืืืืง ืืืื.

ืืคืฉืจ ืืชืงื ืืืช ืขื ืืื ืืชื ืฉืืืช ื critical sections ืืื ืืชืช ืืื ืืื ืื ืขืื ืฉืื ื

ื ืฉืื ืื ืฉ Critical ืืื ืื ืื ืื ื ืขืืื ืืืง ืืื ืืขืืงืจ ืืืืืื ืฉืืื compiler directive ืืืื ืืจืื ืคืขืืื ืืื ืื ื ืืช ืืืืืืช ืืืฆืข ื ืขืืืืช ืืื ืืืืช ืืืชืื ืืืฆื ืืชืืื ืืช. ืืืืืืช ืืืืืื ืฉืื ืืื ืืชืช ืฉืืืช hardcoded ืืื ืขืืืื ืื ืฉืขืืื ืืืฆืืจ ืืฆืืื ืฉื ื ืขืืื ืฉืื ืืฆืืจื.

ืืืฉื ืื ื ืกืชืื ืขื ืงืืข ืืงืื ืืื ืฉื ืืขื dfs_visit ืืื ืฉืงืืข ืืงืื ืืงืจืืื ื ืืขื ืืช ืื ืthreads ืืื ืื ืกืืจืงืื ืดืขืืืงืืืด ืฉืื ืื ืืืืจื ืืขืฅ. ืืื ืืื ืืืื ื ืืื ืืื ืืฉ ืฆืืจื ืืืฆืืจืช ืงืืข ืงืื ืงืจืืื ืื ืื ืื ื ื ืืฉืื ืืืืชื ืงืืืงืื ืื ืื. ื ืจืฆื ืืื ืืช ืื ืื ืื ืฉื ืืชื ืื ืขืื ืืื ืงืืืงืื.
ืืฉื ื ืืื ืคืื ืงืฆืืืช ืฉื ืืชื ืืืฉืชืืฉ ืืื ืืขืืืื ืขื ืื ืขืืืื ื OpenMP

ื ืืื ืืื ื ืืชื ืืืฆืข ืฉืื ืื ืืงืื ื DFS ืขื ืื ืขืืืื ืืืงืื ืจืืช ืืงืืืืืืช ืืืืื ืืืชืจ ืขื ืืื ื ืขืืื ืจืง ืืขืช ืืฆืืจื
global variables: omp_lock_t locks[|V|]
DFS(G=(V,E)) {
#pragma omp parallel for
for ๐ฃโ V
visited[v] โ WHITE
omp_init_lock(&locks[v])
for ๐ฃโ V
if visited[v] = WHITE
#pragma omp parallel
#pragma omp single
dfs_visit (v)
for ๐ฃโ V
omp_destroy_lock(&locks[v])
}
dfs_visit (v) {
visited[v] โ BLACK
for ๐ขโ neighbors[v]
omp_set_lock(&locks[u])
if visited[u] = WHITE
visited[u] โ GRAY
#pragma omp task
dfs_visit(u)
omp_unset_lock(&locks[u])
}
ื ืฉืื ืื ืฉืื ืื ื ื ืืขืืื ืจืง ืืช ืืื ืขืื ืฉื ืงืืืงืื ืกืคืฆืืคื ืฉื ืื ืก ืืชื ืื ื if visited(u) , ืืืืคื ืืื, ืื ืื ื ืืื ืขืื ืืฉื ื threads ืืืื ืก ืืงืื ืืจืงืืจืกืื ืื ืืืืจื ืืจืืฉืื ืฉืืืื ืก ืืฉื ื ืืช ื flag ื WHITE ื GRAY. ืชืื ืืื ืื ืื ื ืืืคืฉืจืื ืืฉื ื threads ืฉืกืืจืงืื ืงืืืงืืืื ืฉืื ืื, ืืืืฉืื ืืฆืืจื ืืงืืืืืช.
ืืจื ื ืืกืคืช ืืืฉืื ืืช ืืืชื ืชืืฆืื ืจืฆืืื ืืื ืืืืฆืขืืช Atomic instruction. ื ืืืืจ ืฉ ืคืขืืืืช ืืืืืืืช ืื ืคืชืจืื ืืืืจืชื ืืืขืืช ื mutual exclusion ืฉืืืืืื ืฉืจืง thread ืืื ืืืื ืืืฆืข ืืช ืืคืขืืื ืืืืืืืช ืืื ืจืืข ื ืชืื ืืืื ืืืื ืข ื race conditions.
ืืืืื ืืืืืชื ืืื ืคืขืืื ืืืืืืช ืืืื ืื ืขืืืื ืืื ืฉืืืืฆืขืืช ืฉืืืืฉ ืืคืขืืืืช ืืืืืืืช , ืืื overhead ืฉื ืืงืคืืช ืืคืขืืื ืฉื threads ืืฉืืืจืช ืืืฆื ืฉืืื ืขื ืืจืืข ืฉืื ืืืืืื ืืจืืฅ.
ื mutual exclusion ื atomic ืืื ืืจืืช ืืืืืจื, ืืขืืืช Locks ืืื ืืื ืื ืืืืืง ืืช ื threads ื busy wait (ืืฆื ืฉืื ื thread ืืืืื ืืื ืืขืื ืขื ืืืชื ื).

ืืืืืืืืช ืืื ืืกืืคืงืช ืขื ืืื ืืืืจื, ืืฉืจ ืืฉืืืชื ืืช ืืืคืจืขืืช ืืืขืื ืืืชืืื ืืืฉืืืชื ืืช ืืืืฉื ืืืขืื -m (ืขื ืืื ื ืขืืืช data bus), ืขื ืืืืฆืืข ืืืจืื ืืืืืืช ืืืืืื.

ืื ืฉืืืืื ืืชืื ืืืืืง atomic ืืื ืืคืขืืื + ืืงืื ืื ืดื. ืืคืื ืงืฆืื do some work ืืื ืืื ื ืืืืืืช ืืืกืคืจ threads ืจืฆืื ืืืงืืื.

ื ืืชื ืืจืืืช ืฉืื ื- threads ืขืืืืื ืืืงืืื, ืืจืง ืืืืฉื ื- x ืืื ื ืืกืื ืืจื ืช.
ืืกืื ืชืงืก ืืื ืืืฆืืจื






ืขื ืคื ืื ื ืจืื ืฉืืงืจืืื ืืืืืืืช ืืื ืืืืชืจืช ืฉืื ืื ืืืขืื ืฉืืกืคืจ threads ืืงืจืื ืืืืชื ืขืจื ืืืืฆืขื ืืฉืื ืฉืื ืืืฉืชื ื? ืืืขืื ืืชืืืื ืืืฉืจ ืชืืืืช ืืขืจื ืฉื ืืืฉืชื ื ื ืืฆื ืืืชืืืช ืฉืืื ืื align. ืืืฆื ืื ืขืืื ืืงืจืืช ืืฆื ืฉืื ืื ืื ื ืืืฆืขืื ืืกืคืจ ืืืฉืืช ืRAM ืจืง ืืื ืืืืื ืขืจื ืฉื ืืฉืชื ื ืืืืฆื ืืื ืื ื ืงืจื ืืช ืืขืจื ืขืืื ืืืืืช ืืฆื ืฉืชืื ืืื ืงืจืืื ืฉื ืืืช ืืื ืืืืฉืชื ื ืืืืช ืืฉื ื ืืฉืชื ื ืชืื ืืื ืื ืื ื ืืืืจ ืืช ืืคืขืืื ืืืืืืืช (ืื ื ืขืืื ืขืaligned addresses).
ืืืืืื - ืฉืงืจืืืืช ืืืืจืื ืืชืืฆืขืืช ื- chunks ืฉื 64 bits, ืืื ืืืชืืืช ืฉืืชืืืงืช ื- 8 . ืื ืืฉืชื ื short x ื ืืฆื ืขื ืืชืคืจ, ื ืฆืืจื ืฉืชื ืืืฉืืช ืืืืจืื ืืื ืืืืื ืืช ืฉื ื ื- bytes ืฉื x. ืืื ืงืจืืื ืจืืฉืื ื ืืงืจืืื ืฉื ืืื ืขืืื ืืืื ืก thread ืืืจ ืฉืขืืื ืืืจืืก ืืช ืืงืจืืื ืฉื x.


ืืืืื ืืชืืืื ืื ืืืฆืื ืฉื ืฉื ื threads, ืืืฉืจ thread ืืื ืื ืกื ืืงืจืื ืืช ืืขืจื ืฉื x, ื- thread ืฉื ื ืื ืกื ืืืชืื ืขืจื ืืืฉ ื- x. ืืกืืฃ ืืงืจืืื v ืืงืื junk value.
ื ืจืื ืฉืืืืฉ ืืคืขืืืืช ืืืืืืืช ืืืืืืฉ dfs

ืืื ืืฉืชืืฉื ื ื compare and capture ืคืขื ืืืช ืื ืคืขื ืฉื ืื ืกืื ื dfs visit. ืืฆื ืื ืืืจื ืืื ืฉืื ืงืืืงืื ืืฆืืจื ืืืืืืช ืฉืืืจ ืืช ืold value ืฉื ืงืืืงืื ืฉืืื ืืืงืจ ืืื ืืืืขื ืืชืืื ืขืจื ืืืฉ. ืื ืืขืจื ืืืฉื ืืื white ืื ืืืงืจืื ืื. ืืืื ืฉืคืขืืื ืcapture ืืื ืืืืืืช, ืื ืืื ืืฉืฉ ืฉืืชื ืื ืืชืงืืื ืขืืืจ ืฉื ื threads ืฉืืืงืจืื ืืืืชื ืงืืืงืื.
ื ืจืฆื ืืื ื ื ืชืื ืื ืฉื ืจืฉืืื ืืงืืฉืจืช ืฉืชืืืืช ืืืืงืืื.
ื ืจืฆื ืืืงืื ืคืื ืงืฆืืืช ืinsert ืืจืืืื ืืชืืื ืsorted_insert ืฉืืื ืืก ืืืืจืื ืืฆืืจื ืืืืืื ืช ืืจืฉืืื.
ืืงืื ืกืืจืชื ืื ืืจืื ืื
void sorted_insert(node_t *head, int val) {
/* Find the right place to insert */
node_t *ptr = head->next;
node_t *prev = head;
while (ptr != NULL && ptr->value < val) {
prev = ptr;
ptr = ptr->next;
}
/* Insert the new node */
node_t *new_node = malloc(sizeof(node_t));
new_node->value = val;
new_node->next = ptr;
prev->next = new_node;
}
ืื ืื ื ื ืงืื ืืช ืืืฆืืืข ืื ืขืื ืืขืจื ืื ืืืื ืฉื ืืืฆืืืข ืืืืืจ ืืจืฉืืื ืืงืืฉืจืช ืงืื ืืืขืจื ืฉื ืจืฆื ืืืื ืืก. ืืจืืข ืฉืืืขื ื ื ืื ืืก ืืช ื node ืืืืฉ.
ื ื ืกื ืืืชืื ืืช ืืงืื ืืื ืืื ืืชืืื ืืืงืืืืืืช ืืื ืฉืืืชืจ ืืืืจื ืืืืฆืขืืช ืืื ืืกื ืืจืื ืืฉืื ืื.
ืืืืืืฉ ืืื ื ืืืื ืืืื ืืืฉืชืืฉ ืืื ืขืื ืืื ืืชืื ืืคืื ืงืฆืื ืฉื sorted_insert. ืืจืื ืคืขืืื ืืคืชืจืื ืฉื ืืืืืจืืชืืื ืืงืืืืืื ื ืจืฆื ืืืชืืื ืืืืืื ืืืื ืืื ืืคืชืจืื ืื ืืืื ืืืืชืจ ืืืคืชื ืืืชื.
void sorted_insert(node_t *head, int val) {
/* Find the right place to insert */
omp_set_lock(&lock);
node_t *ptr = head->next;
node_t *prev = head;
while (ptr != NULL && ptr->value < val) {
prev = ptr;
ptr = ptr->next;
}
/* Insert the new node */
node_t *new_node = malloc(sizeof(node_t));
new_node->value = val;
new_node->next = ptr;
prev->next = new_node;
omp_unset_lock(&lock);
}
ืืืืืืฉ ืืื ืืืคื ืืช ืืืืืง ืืื ืืกืืจืชื ืืืื ืจืืช ืืืงืืืืืืช ืืื ืืกืืจืชื ืืืชืืกืคืช ื overhead ืฉื ืืฆืืจืช threads , ืืงืื ืฉืื ื ืืืื ืืจืืข ืืืจืื ืืืงืื ืืกืืจืชื.
ืืืจืกื ืืฉื ืืื ืฉืื ื ืชืฆืืข ืจืขืืื ืขื ืืงืืืืืืช ืืืชืจ ืืืืื.
ืื ืื ื ื ืจืฆื ืฉืื thread ืฉืงืืจื ืืคืื ืงืฆืื sorted_insert ืืืคืฉืจ ื threads ืฉืืืื ืืืจืื ืืขืืื ืจืง ืขื ืจืืฉื ืฉื ืืจืฉืืื. ืืขืื ืื ืื ืื pipeline ืื ืฉืืืงืื ืฉืื thread ืืฆืืจื ืืืฆืื ืืืื ืืืงื ืืช ืืขืจื ืฉืื ืืจืฉืืื ืืื ืืืคืฉืจ ื thread ืืื ืืจืืฅ, ืืื ืืืกื ืthreads ืืืจืื ืจืง ืชืช ืจืฉืืื ืืื ืืช ืืืืคืฉืจ ืืื ืืขืืื ืขื ืืฉืืืืืช ืขื ืฉืืื ืืกืืื.
void sorted_insert(node_t *head, int val) {
/* Signal start of search */
omp_set_lock(head->lock);
/* Find the right place to insert */
node_t *ptr = head->next;
node_t *prev = head;
while (ptr != NULL && ptr->value < val) {
omp_set_lock(ptr->lock);
omp_unset_lock(prev->lock);
prev = ptr;
ptr = ptr->next;
}
/* Insert the new node */
node_t *new_node = malloc(sizeof(node_t));
new_node->value = val;
new_node->next = ptr;
new_node->lock = malloc(sizeof(omp_lock_t));
omp_init_lock(new_node->lock);
prev->next = new_node;
omp_unset_lock(prev->lock);
}
ืืขืช ืืื ืืืืจ ืืจืฉืืื ืืฉ ืื ืขืื ืืฉืื. ืื thread ืฉื ืื ืก ื ืืขื ืืช ืptr ืฉืขืืื ืืื ืืจืืข ื ืืฆื ืืจืฉืืื ืืืฉืืจืจ ืืช ืืงืืื ืืืื ืืื ืืืฉืื.
ืืืจืกื ืืฉืืืฉืืช ืฉื ืชืืืื ืืืงืืืืืืช ืฉื sorted_insert ืชืขืืื ืืืืคื ืืื-
ื ืืคืฉืจ ืthreads ืืืฆืื ืืช ืืืงืื ืptr ืฉืืืจืื ืืืืจ ืืืื ืก ืืงืืืงืื ืืืืฉ ืืฆืืจื ืืงืืืืืช ืืื ืื ืื ืื ืกื ืืจืื.
ืืจืืข ืฉthread ืืืฉืื ืืฆื ืืช ืptr ืืื, ืืื ืื ืกื ืื ืขืื ืืช ืืืฆืืืข prev , ืื ืฉืืฆืืืข ืptr.
ืืกืืื ืฉืืื ืื ืกื ืื ืขืื ืืืชื ืืื ืืืื ืฉืืืื ืืืืืช ืฉืชืื ืืื ืืืืคืืฉ ืฉื ืptr ืงืจื ืืฆื ืฉ threads ืืืจืื ืืืกืืคื ืขืจืืื ืืื prev ื ptr ืืืขืช ืืืฆื ืืืจ ืื ืขืืื ื.
ืืช ืื ืืคืฉืจ ืืขืฉืืช ืขื ืืื ืืฉืืืื ืืื ืptr ืืืื prev.next . ืื thread ืืืจ ืืืกืืฃ ืืืืจ ืืื prev ื ptr ืืืฉืืืื ืืืืช ืชืืื ืื ื ืืช ืื. ืืืฆื ืื ืื ืื ื ืืืฆืขืื ืืืืืืง ืืช ืืืชื ืืงืื ืืืจืกื v2 ืจืง ืฉืืคืขื ืื ืื ืจืื ืืืื ืขื ืชืช ืจืฉืืื ืืฆืืืฆืืช ืืืจืื.
ืืืกืืฃ ืืืฆืขืื ืืื ืกื ืฉื ืืขืจื ืืืืฉ ืืจืฉืืื.
void sorted_insert(node_t *head, int val) {
/* Find the right place to insert */
node_t *ptr = head->next;
node_t *prev = head;
while (ptr != NULL && ptr->value < val) {
prev = ptr;
ptr = ptr->next;
}
/* Lock the elment that may be modified */
omp_set_lock(prev->lock);
/* Confirm that the element is still in the right place */
if (prev->next != ptr) {
ptr = prev->next;
while (ptr != NULL && ptr->value < val) {
omp_set_lock(ptr->lock);
omp_unset_lock(prev->lock);
prev = ptr;
ptr = ptr->next;
}
}
/* Insert the new node */
node_t *new_node = malloc(sizeof(node_t));
new_node->value = val;
new_node->next = ptr;
new_node->lock = malloc(sizeof(omp_lock_t));
omp_init_lock(new_node->lock);
prev->next = new_node;
omp_unset_lock(prev->lock);
}