インテル® C++ コンパイラー XE 13.1 ユーザー・リファレンス・ガイド

GAP メッセージ (診断 ID 30538)

メッセージ

関数の呼び出し (行 %d)、IF 条件 (行 %d)、早期終了 (行 %d) を含むコードブロックをループの外側に移動することで、行 %d のループを並列化できます。

アドバイス

ループを並列化するために、関数呼び出しと関連するリターンをループの中から (ループの前に持ってくるなどして) 移動します。

このようなループ中の関数とリターンは、通常ループ中のエラー条件を処理します。プログラムのセマンティクスを変更することなく、このエラーチェックをループの実行前に行える場合、コンパイラーはループを並列化してパフォーマンスを向上できる可能性があります。

次の例について考えてみます。

extern int num_nodes;
typedef struct TEST_STRUCT {
    // Coordinates of city1
    float latitude1;
    float longitude1;
 
    // Coordinates of city2
    float latitude2;
    float longitude2;
} test_struct;
 
extern int *mark_larger;
extern float *distances, **matrix;
extern test_struct** nodes;
extern test_struct ***files;
extern void init_node(test_struct *node, int i);
extern void process_nodes(void);
float compute_max_distance(void);
 
extern int check_error_condition(int width);
 
#include <math.h>
#include <stdio.h>
 
void process_nodes(int width)
{
  float const R = 3964.0;
  float temp, lat1, lat2, long1, long2, result, pat2;
  int m, j, temp1 = num_nodes;
 
      nodes = files[0];
      m = 1;
 
#pragma loop count min(4)
#pragma parallel
      for (int k=0; k < temp1; k++) {
 
	        if (check_error_condition(width)) {
	            return;
	        }
 
         lat1 = nodes[k]->latitude1;
	        lat2 = nodes[k]->latitude2;
 
	        long1 = nodes[k]->longitude1;
	        long2 = nodes[k]->longitude2;
 
	        // Compute the distance between the two cities
	        temp = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * 
	                                              cos(long1-long2);
	        result = 2.0 * R * atan(sqrt((1.0-temp)/(1.0+temp)));
 
	        pat2 = 0;
	        for(j=0; j<width; j++) {
	          pat2 += distances[j];
	          matrix[k][j] = distances[k]+j;
	        }
	        // Store the distance computed in the distances array
	        if (result > distances[k]) {
	            distances[k] = result + pat2;
	        }
      }
}

この例では、コンパイラーは行 38 のループを並列化できません。

安全であることが分かっている場合は、次のようにプログラムコードを変更します。

extern int num_nodes;
typedef struct TEST_STRUCT {
    // Coordinates of city1
    float latitude1;
    float longitude1;
 
    // Coordinates of city2
    float latitude2;
    float longitude2;
} test_struct;
 
extern int *mark_larger;
extern float *distances, **matrix;
extern test_struct** nodes;
extern test_struct ***files;
extern void init_node(test_struct *node, int i);
extern void process_nodes(void);
float compute_max_distance(void);
 
extern int check_error_condition(int width);
 
#include <math.h>
#include <stdio.h>
 
void process_nodes(int width)
{
  float const R = 3964.0;
  float temp, lat1, lat2, long1, long2, result, pat2;
  int m, j, temp1 = num_nodes;
 
      nodes = files[0];
      m = 1;
 
      if (check_error_condition(width)) {
	  return;
      }
 
#pragma loop count min(4)
#pragma parallel
      for (int k=0; k < temp1; k++) {
 
         lat1 = nodes[k]->latitude1;
	        lat2 = nodes[k]->latitude2;
 
	        long1 = nodes[k]->longitude1;
	        long2 = nodes[k]->longitude2;
 
	        // Compute the distance between the two cities
	        temp = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * 
	                                              cos(long1-long2);
	        result = 2.0 * R * atan(sqrt((1.0-temp)/(1.0+temp)));
 
	        pat2 = 0;
	        for(j=0; j<width; j++) {
	          pat2 += distances[j];
	          matrix[k][j] = distances[k]+j;
	        }
	        // Store the distance computed in the distances array
	        if (result > distances[k]) {
	            distances[k] = result + pat2;
	        }
      }
}

確認

関数の呼び出しがループ内のどの演算にも依存していないこと、およびこのコード変更によってオリジナルのプログラムのセマンティクスが変更されないことを確認してください。


このヘルプトピックについてのフィードバックを送信