インテル®コンパイラー OpenMP*入門 デュアルコア・マルチコア対応アプリケーション開発@ <<  10  >> 並列化コンパイルフロー 自動並列化コンパイラーでは、プログラム内でループとして形成される一連の処理における、その実行タスクとデー タフローを解析します。 実際には、プログラム中で利用される配列や変数がループ中でどのようにアクセスされるかを 解析します。このデータアクセスのパターンにおいて、ループの実行時にそのデータ参照において競合が無い事を確 認する依存性解析を行います。データアクセスのパターン解析では、プログラム内の配列や変数が、並列化した場合 に各スレッドが「Private」として個々に利用するものであるか、「Shared」としてスレッド間で共有されるかを判定します。 また、自動並列化では、ループ処理のタスクで並列に実行できる部分と、逐次処理する部分も分離して、並列化 処理のためのコードへの変換がなされます。実際には、スカラー最適化やループ最適化 (レジスター内でのベクトル 化やメモリー最適化) といった最適化機能と並列化機能の 2 つは緊密に統合されて、キャッシュの局所性を高め、ス レッドレベル以外での並列性を効率的に利用しています。 自動並列化では、入れ子になった多重ループの場合、できるだけ外側のループを並列化の対象とするようになっ ており、並列処理のオーバーヘッドを最大限減らすことに寄与します。例えば、二重にネストされたループの場合、 最内側ループについては、ベクトル化をはじめキャッシュの局所性を高め、レジスター利用の最適化を最大限に図り、 計算回数とメモリー参照を最小化するような最適化の適用を目指し、外側ループでマルチスレッド・コードを生成する ような最適化を行います。自動並列化での並列処理は、 一般には、「細粒度」での並列処理となります。 例えば、 次のようなプログラムの自動並列化を考えてみましょう。 for (i=1; i<100; i++) {   a[i] = a[i] + b[i] * c[i]; } プログラム スタック データ オリジナル 並列処理のための コード変換 複数のタスクに分割 並列化されたプログラム Program SPMD_Emb_Par () {    TYPE *tmp, *func();    global_array Data(TYPE);    global_array Res(TYPE);    int N = get_num_procs();    int id = get_proc_id();    if (id==0) setup_problem(N,DATA);    for (int I= 0; I<N;I=I+Num){         tmp = func(I);         Res.accumulate( tmp);    } } Program SPMD_Emb_Par () {    TYPE *tmp, *func();    global_array Data(TYPE);    global_array Res(TYPE);    int N = get_num_procs();    int id = get_proc_id();    if (id==0) setup_problem(N,DATA);    for (int I= 0; I<N;I=I+Num){         tmp = func(I);         Res.accumulate( tmp);    } } Program SPMD_Emb_Par () {    TYPE *tmp, *func();    global_array Data(TYPE);    global_array Res(TYPE);    int N = get_num_procs();    int id = get_proc_id();    if (id==0) setup_problem(N,DATA);    for (int I= 0; I<N;I=I+Num){         tmp = func(I);         Res.accumulate( tmp);    } } Program SPMD_Emb_Par () {    TYPE *tmp, *func();    global_array Data(TYPE);    global_array Res(TYPE);    int Num = get_num_procs();    int id = get_proc_id();    if (id==0) setup_problem(N, Data);    for (int I= ID; I<N;I=I+Num){         tmp = func(I, Data);         Res.accumulate( tmp);    } } 共有データ タスク、ローカルデータと 共有データの明確化 複数のタスクを分割し 逐次処理部分の分離 共有データ 分割されたタスクを グループ化