操作速度を向上させるOpenMP並列操作呼び出しメソッドC ++

 1 #include <iostream>
   #include <omp.h>
 2 int main(){
 3     int sum = 0;
 4     int a[10] = {1,2,3,4,5,6,7,8,9,10};
 5 #pragma omp parallel for reduction(+:sum)
 6     for (int i=0;i<10;i++)
 7         sum = sum + a[i];
 8     std::cout<<"sum: "<<sum<<std::endl;
 9     return 0;
10 }

#progma omp parallel forは、forループの並列実行を意味します

合計変数は正規化されます(加算+)。そうしないと、合計変数の操作に競合が発生し、結果に一貫性がなくなる可能性があります。

正規化できるその他の記号:

還元(演算子:var1、val2、...)

演算子変数と規則変数の初期値は次のとおりです:

演算子データ型デフォルトの初期値

+整数、浮動小数点0

-整数、浮動小数点0

*整数、浮動小数点1

&整数すべての桁は1です

|整数0
^整数0

&&整数1

||整数0

最大値を並行して取る

 1 #include <iostream>
 2 int main(){
 3     int max = 0;
 4     int a[10] = {11,2,33,49,113,20,321,250,689,16};
 5 #pragma omp parallel for
 6     for (int i=0;i<10;i++)
 7     {
 8         int temp = a[i];
 9 #pragma omp critical
10         {
11             if (temp > max)
12                 max = temp;
13         }
14     }
15     std::cout<<"max: "<<max<<std::endl;
16     return 0;
17 }

#pragma ompcriticalは、クリティカルセクションが競合を回避することを確認しますが、待機を引き起こす可能性もあり、並列効率が低下する可能性があります。

並列実行の別の方法SECTION

 1 #pragma omp parallel sections
 2 {
 3     #pragma omp section
 4     {
 5         function1();
 6     }
 7   #pragma omp section
 8     {
 9         function2();
10     }
11 }

ROSコンパイルの場合、CMakelistsに追加する必要があります

find_package(OpenMP)
if (OPENMP_FOUND)
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()

スケジューリング戦略を定義する

#pragma omp parallel for schedule(static、2)//静的スケジューリング戦略。forループは2回の反復ごとにタスクに分割されます

スケジューリング戦略機能の適用性

静的ループ変数領域はn個の等しい部分に分割され、各スレッドはn個のタスクをスコアリングします。各CPUのパフォーマンスにほとんど違いはありません。   

動的ループ可変領域はn個の等しい部分に分割されます。スレッドが1つの部分を実行した後、実行する必要のある他のタスクが実行されます。CPU間の動作能力には大きな違いがあります。

ガイドループ可変領域は、大から小までn個に分割されています。操作方法は動的に似ています。タスク数が動的以上であるため、スケジューリングのオーバーヘッドを削減できます。

ランタイムは、実行時に上記の3つのスケジューリング戦略のいずれかを適用します。デフォルトでは静的を使用します

 

同期メカニズム

単一のスレッドによってのみ実行されるコードセグメントの前に使用されるsingleは、次のコードセグメントが単一のスレッドによって実行されることを示します。

バリア。並列ゾーンでコードのスレッドを同期するために使用されます。すべてのスレッドは、バリアに対して実行されると停止し、すべてのスレッドがバリアに対して実行されると実行を継続する必要があります。

マスター、#pragma omp materを介して、対応する並列プログラムブロックがメインスレッドによってのみ完了することを宣言します。

nowaitはバリアをキャンセルするために使用され、その使用法は次のとおりです。

#pragma omp for nowait //不可用#pragma omp parallel for nowait

または

#pragma omp single nowait

#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件

int main()
{
#pragma omp parallel
    {
#pragma omp for nowait
        for (int i = 0; i < 1000; ++i) 
        {
            std::cout << i << "+" << std::endl;
        }
#pragma omp for
        for (int j = 0; j < 10; ++j) 
        {
            std::cout << j << "-" << std::endl;
        }
    }
    
    return 0;
}

最初のforループの2つのスレッドの1つが実行された後、実行が続行されるため、最初のループの+と最初のループの-が同時に出力されます。

#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件

int main()
{
#pragma omp parallel
    {
#pragma omp master
        {
            for (int j = 0; j < 10; ++j) 
            {
                std::cout << j << "-" << std::endl;
            }
        }

        std::cout << "This will printed twice." << std::endl;
    }

    return 0;
}

比較した後、単一層のforループは、多数の繰り返しが追加された場合に効果的ですが、他の層は効果がなく、さらに遅くなります。

参照元:

https://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html

https://blog.csdn.net/donhao/article/details/5652552

https://blog.csdn.net/donhao/article/details/5657371

https://blog.csdn.net/donhao/article/details/5657428

https://blog.csdn.net/SHU15121856/article/details/79350474

https://blog.csdn.net/weixinhum/article/details/97808767

https://blog.csdn.net/donhao/article/details/5656390

https://blog.csdn.net/donhao/article/details/5657717

おすすめ

転載: blog.csdn.net/li4692625/article/details/109377402