2019/10/23

OpenMPを使用した並列化

背景


OpenMPを利用して並列化を行い、処理を高速化する必要が出てきたため、OpenMPで並列化処理を記述する方法について記述する

記事の目的


OpenMPで並列化処理を行う際のテンプレートを作成する

OpenMP


ここでは、OpenMPを利用したCプログラムの記述方法について記載する。

OpenMPとは

OpenMP
OpenMPは、OpenMP ARBが提供する並列コンピューティング環境において共有メモリのマルチスレッド処理をサポートするために開発されたAPIである。

利点

  • マルチスレッド並列なプログラムをディレクティブを挿入するだけで実現できる
  • gccなどで標準サポートされており、導入が容易である

テンプレート

OpenMPを利用して並列処理を行うテンプレートを記載する。


  1. // CMakeLists.txt に追記
  2. # For OpenMP
  3. find_package(OpenMP REQUIRED)
  4. if(OpenMP_FOUND)
  5. message(STATUS "Use OpenMP")
  6. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
  7. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
  8. endif()

  1. // openmp_sample_code.cpp
  2. #include <iostream>
  3. #ifdef _OPENMP
  4. // ヘッダーファイルをインクルード
  5. #include <omp.h>
  6. #endif
  7. int main()
  8. {
  9. #ifdef _OPENMP
  10. // スレッド数を設定(今回は4スレッド)
  11. omp_set_num_threads(4);
  12. #endif
  13. #ifdef _OPENMP
  14. // スレッド数取得
  15. std::cout << "The number of processors is "<< omp_get_num_procs() << std::endl;
  16. #endif
  17. #ifdef _OPENMP
  18. // ここから並列処理を行う
  19. // 【注】カッコ内の処理は、スレッド数回実行される
  20. #pragma omp parallel
  21. #endif
  22. {
  23. int a = 0, b= 0;
  24. #ifdef _OPENMP
  25. // section毎に並列処理を行う
  26. #pragma omp sections
  27. #endif
  28. {
  29. #ifdef _OPENMP
  30. #pragma omp section
  31. #endif
  32. {
  33. // 並列化される処理 1
  34. a ++;
  35. }
  36. #ifdef _OPENMP
  37. #pragma omp section
  38. #endif
  39. {
  40. // 並列化される処理 2
  41. b ++;
  42. }
  43. }
  44. #ifdef _OPENMP
  45. // ここまでの並列処理が完了するまで待機
  46. #pragma omp barrier
  47. // シングルスレッド処理
  48. // 【注】マルチスレッド処理内におけるプライベート変数は引き継がれない場合がある
  49. // このコードでは、aまたはbのどちらかが0になる
  50. #pragma omp single
  51. #endif
  52. {
  53. std::cout << "a=" << a << std::endl;
  54. std::cout << "b=" << b << std::endl;
  55. }
  56. }
  57. size_t i;
  58. int c = 0;
  59. int sum = 0;
  60. #ifdef _OPENMP
  61. // forループを並列化
  62. // 【注】 #pragma omp parallel内で#pragma omp parallel forすると、2重に並列化するため注意
  63. //     上記の場合、#pragma omp parallel forを#pragma omp forとする
  64. // iを各スレッドのプライベート変数に指定
  65. // 並列化した際にスレッドをを静的(static)に割り当て、チャンクサイズを2に指定
  66. // (この場合、i=0,1,4,5,...とi=2,3,6,7,...でスレッドが作られる)
  67. // (動的に割り当てる場合はdynamicとする。ただし、スレッド生成コストが増大する)
  68. // sumは、i*iの処理が並列で行われた後、+=の処理がまとめて行われる
  69. // orderedは、forループ内にorderedセクションがあることを示す
  70. #pragma omp parallel for private(i) schedule(static, 2) reduction(+, sum) ordered
  71. #endif
  72. for(i = 0; i < 10; ++i)
  73. {
  74. sum += i*i;
  75. #ifdef _OPENMP
  76. // criticalセクション内は、最大で1つのスレッドしか実行されない
  77. // ただし、スレッド待ちの処理コストが発生する
  78. #pragma omp critical
  79. #endif
  80. {
  81. c += i*i;
  82. std::cout << "c=" << c << std::endl;
  83. }
  84. #ifdef _OPENMP
  85. // orderedセクション内は、順番に実行される
  86. #pragma omp ordered
  87. #endif
  88. {
  89. std::cout << "i=" << i << std::endl;
  90. }
  91. std::cout << "sum=" << sum << std::endl;
  92. }
  93. }

まとめ


  • OpenMPでプログラミングをする際のテンプレートを調査、記載した

参考文献



変更履歴


  1. 2019/10/23: 新規作成
  2. 2019/12/15: コード修正

0 件のコメント:

コメントを投稿

MQTTの導入

背景 IoTデバイスの接続環境構築のため、MQTT(mosquitto)の導入を行った。 記事の目的 MQTT(mosquitto)をUbuntuに導入する mosquitto ここではmosquittoについて記載する。 MQTT MQTT(Message Qu...