OpenMP กับ race condition

ความรู้เบื้องต้น

  • C – programing
  • OpenMP

การเขียนโปรแกรมบนสถาปัตยกรรม shared momory ปัญหาหนึ่งที่เรามักจะพบคือ race condition หรือ “ภาวะแข่งขัน”   ยกตัวอย่าง การเขียนโปรแกรมด้วย OpenMP ในลักษณะนี้นะครับ

1:  int i=0;
2:  #pragma omp parallel
3:   i++;
4:  printf(“%3d”,i);

โค๊ดนี้ผมนำไปรันบน intel processor แบบ quad core ปรากฏว่าผลลัพธ์ให้ค่าที่เหวี่ยงไปมา ตัวอย่าง ผลลัพธ์ของเครื่องผม 20 รอบคำสั่งคือ

3  3  4  3  4 3  3 4  4  4  4  4  3  2  4  3  3  3  4  4

บรรทัดที่ 3 ของโปรแกรม เกิด race condition ขึ้น เนื่องจากตัวแปร i เป็นตัวแปรที่ใช้ร่วมกัน สำหรับ thread ทั้ง 4 ตัว ดังนั้นจังหวะที่อ่านและเขียนข้อมูลถ้าไม่มีลักษะเป็น atomic จะทำให้เกิดปัญหานี้ขึ้นได้

OpenMP มี directive ชื่อว่า atomic สำหรับช่วยให้ thread ใดๆ สามารถอัปเดตของตัวแปรใด ๆ ได้โดยที่ไม่ต้องกังวลว่า ณ เวลานั้นจะมี thread ตัวอื่นเข้ามาเรียกใช้งาน ดังนั้นจากตัวอย่างข้างบนเราสามารถแก้ไขโดยใช้ atomic ได้ดังนี้

1:  int i=0;
2:  #pragma omp parallel
3: {
4:   #pragma omp atomic
5:      i++;
6:  }
7:  printf(“%3d”,i);

ผลลัพธ์ 20 รอบคำสั่ง เมื่อแก้ไขโปรแกรมแล้ว

4  4  4  4  4  4  4 4  4  4  4  4  4  4  4  4  4  4  4  4

สำหรับ directive atomic นั้นไม่สามารถกำหนดให้ block ของ code ได้ ถ้าต้องการป้องกันตัวแปรมากกว่า 1 ตัว วิธีการหนึ่งคือ ต้องเขียน #pragma omp atomic ให้กับทุกๆตัวแปร ดังนี้

1:  int i=0,j=0;
2:  #pragma omp parallel
3: {
4:   #pragma omp atomic
5:      i++;
6:   #pragma omp atomic
7:     j++;
8:  }
9:  printf(“i=%d,j=%d\n”,i,j);

OpenMP มี directive อีกตัวหนึ่งที่ให้ใช้ได้ง่ายกว่า คือ critical ซึ่งหน้าที่จะเหมือนกับ atomic เพียงแต่เราสามารถกำหนดส่วนของ block ลงไปได้เลย ซึ่งจะช่วยลดความยุ่งยากในการเขียนโปรแกรมไปได้พอสมควร

1:  int i=0,j=0;
2:  #pragma omp parallel
3: {
4:   #pragma omp critical
5:   {
6:      i++;
7:      j++;
8:    }
9:  }
10:  printf(“i=%d,j=%d\n”,i);

ใส่ความเห็น