次の方法で共有


Vectorizer and Parallelizer Messages

アクティビティの理由コードと情報メッセージを出力するに 自動並列のエラーおよび警告 を設定する Visual C++ コンパイラ オプション /Qpar-report/Qvec-report を使用できます。ここでは、理由コードとメッセージについて説明します。

情報メッセージ

レベル、指定したレポートには、次の情報メッセージの 1 つが、各ループで表示されます。

理由コードに関する情報については、このトピックの次の手順を参照してください。

情報メッセージ

説明

5001

ループ vectorized。

5002

推論すること vectorized 値を「説明」ループ。

5011

並列ループになります。

5012

推論することで並列ループに見つかりません。「説明」。

5021

プラグマとループを関連付けることができません。

理由コード

次のセクションでは、自動 parallelizer の原因コードを、自動 vectorizer 示します。

JJ658585.collapse_all(ja-jp,VS.110).gif50x

X の 50 の理由コードが自動 parallelizer と自動 vectorizer に適用されます。

理由コード

説明

500

これで、サンプル ケースのいくつかに関する一般的なメッセージ ループが含まれています、複数の終了を場合、またはループのヘッダーでは、ルーティングの変数を大きくして終了します。

501

ルーティングの変数をローカルではありません; または上限のループ境界は不変ではありません。

502

ルーティングの変数は、単純な +1.以外の何らかの方法で説明します。

503

ループは、例外処理、switch ステートメントが含まれます。

504

ループ本体は、. C++ オブジェクトの破棄を必要とする例外をスローすることがあります。

void code_500(int *A)
{
    // Code 500 is emitted if the loop has non-vectorizable flow.
    // This can include "if", "break", "continue", the conditional 
    // operator "?", or function calls.
    // It also encompasses correct definition and use of the induction
    // variable "i", in that the increment "++i" or "i++" must be the last
    // statement in the loop.

    int i = 0;
    while (i<1000)
    {
        if (i == 4) 
        {
            break;
        }

        ++i;

        A[i] = A[i] + 1;
    }
    // To resolve code 500, use a 'for' loop with single increment of 
    // induction variable.

    for (int i=0; i<1000; ++i)
    {       
        A[i] = A[i] + 1;
    }    
}

int bound();
void code_501_example1(int *A)
{
    // Code 501 is emitted if the compiler cannot discern the
    // induction variable of this loop. In this case, when it checks
    // the upperbound of 'i', the compiler cannot prove that the 
    // function call "bound()" returns the same value each time.
    // Also, the compiler cannot prove that the call to "bound()"
    // does not modify the values of array A.

    for (int i=0; i<bound(); ++i)
    {
        A[i] = A[i] + 1;
    }

    // To resolve code 501, ensure that the induction variable is 
    // a local variable, and ensure that the upperbound is a
    // provably loop invariant value.

    for (int i=0, imax = bound(); i<imax; ++i)
    {
        A[i] = A[i] + 1;
    }
}

int i;
void code_501_example2(int *A)
{
    // Code 501 is emitted if the compiler cannot discern the
    // induction variable of this loop. In this case, 'i' is
    // a global.

    for (i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }

    // To resolve code 501, ensure that the induction variable is 
    // a local variable, and ensure that the upperbound is a
    // provably loop invariant value.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

void code_502(int *A)
{
    // Code 502 is emitted if the compiler cannot discern
    // the induction variable of the loop. In this case,
    // there are three increments to "i", one of which
    // is conditional.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
        ++i;

        if (i < 100) 
        {
            ++i;
        }
    }

    // To resolve code 502, ensure that there is just one 
    // increment of the induction variable, placed in the usual
    // spot in the "for" loop.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}


// compile with /EHsc
void code_503(int *A, int x)
{
    // Code 503 is emitted if there are inadmissible
    // operations in the loop - for example, exception handling and
    // switch statements.

    for (int i=0; i<1000; ++i)
    {
        try 
        {
            A[i] = A[i] + 1;
        }
        catch (...)
        {

        }

        switch (x)
        {
        case 1: A[i] = A[i] + 1;
        case 2: A[i] = A[i] + 2;
        case 3: A[i] = A[i] + 3;
            break;
        }
    }

    // To resolve code 503, try to remove as many switch statements
    // and exception handling constructs as possible.
}

// compile with /EHsc

int code_504_helper();
class C504
{
public:
    C504();
    ~C504();
};

void code_504() {
    // Code 504 is emitted if a C++ object was created and
    // that object requires EH unwind tracking information under
    // /EHs or /EHsc.

    for(int i = 0; i < 1000; ++i)
    {
        C504 c;
        A[i] = code_504_helper();
    }

}

JJ658585.collapse_all(ja-jp,VS.110).gif100x

X の 100 種類の理由コードが自動 parallelizer に適用されます。

理由コード

説明

1000

コンパイラはループ本体のデータの依存関係を検出しました。

1001

コンパイラはループ本体のスカラー変数にストアを検出し、そのスカラーにループを超える使用できます。

1002

コンパイラは既に並列になった内側のループがあるループを並列化しています。

1003

ループ本体がメモリに対して読み取りまたは書き込みを行うことができる基本的な呼び出しが含まれます。

1004

ループ本体にスカラー デクリメントがあります。スカラー縮小は、ループが vectorized 発生することがあります。

1005

no_parallel のプラグマが指定されました。

1006

この関数は openmpが含まれます。この関数の openmp を削除することによってこれを解決します。

1007

ループのルーティングの変数またはループの境界が署名されていない 32 ビット数ではありません (int か long)。ルーティングの変数の型を変更してそれを解決します。

1008

コンパイラによって並列化を保護するためにこのループが十分な処理を実行しないことを検出しました。

1009

コンパイラは、「並列化を試みます」ループが検出されました。ターゲットの for の自動parallelizer ループだけ。

void func();
void code_1000()
{
    // Code 1000 is emitted if the compiler detects a 
    // data dependence in the loop body. 

    // You can resolve this by using the ivdep pragma.
    // CAUTION -- the compiler will trust your
    // assertion that there are no data dependencies
    // in the loop body. If there are, you are generating
    // code that may have race conditions.

#pragma loop(hint_parallel(0))
    //#pragma loop(ivdep) // ivdep will force this through.
    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i-1] + 1;  // data dependence here
        func();             // data dependence here
    }
}

int code_1001()
{
    // Code 1001 is emitted if the compiler detects
    // a store to a scalar variable in the loop
    // body, and that scalar has a use beyond the loop.

    // Resolve this by rewriting your code so
    // that the scalar is not needed.

    int s = 0;
#pragma loop(hint_parallel(0))
    for (int i=0; i<1000; ++i)
    {
        s = A[i];
    }
    return s;
}

void code_1002()
{
    // Code 1002 is emitted when the compiler tries to
    // parallelize a loop that has an inner loop that
    // has already been parallelized.

#pragma loop(hint_parallel(0))
    for (int i=0; i<1000; ++i) // emit code 1002 for this loop
    {
#pragma loop(hint_parallel(0))
        for (int j=0; j<1000; ++j) // this loop gets parallelized
        {
            A[j] = A[j] + 1;
        }
    }
}

extern "C" void __stosb(unsigned char*, unsigned char, size_t);
void code_1003(unsigned char *dst)
{
    // Code 1003 is emitted when the loop body contains an intrinsic
    // call that may read or write to memory.

    // This can be resolved by using the ivdep pragma.
    // CAUTION -- the compiler will trust your
    // assertion that there are no data dependencies
    // in the loop body. If there are, you are generating
    // code that may have race conditions.

#pragma loop(hint_parallel(0))
    //#pragma loop(ivdep) // ivdep will force this through.
    for (int i=0; i<1000; ++i)
    {
        __stosb(dst, 'c', 10);
        A[i] = A[i] + 1;
    }
}

int code_1004()
{
    // Code 1004 is emitted when there is a scalar reduction
    // in the loop body, which can occur if the loop has been
    // vectorized.

    // You can resolve this by rewriting your code so that it
    // does not have a scalar reduction.

    int s = 0;
#pragma loop(hint_parallel(0))
    for (int i=0; i<1000; ++i)
    {
        s += A[i];
    }
    return s;
}

void code_1005()
{
    // Code 1005 is emitted when the 
    // no_parallel pragma is specified.

#pragma loop(no_parallel)
    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

#include <omp.h>

// Compile with /openmp
void code_1006()
{
    // Code 1006 is emitted when this function contains
    // openmp. Resolve this by removing any openmp in this
    // function.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }

#pragma omp parallel num_threads(4)
    {
        int i = omp_get_thread_num();
        A[i] = A[i] + 1;
    }
}

void code_1007()
{
    // Code 1007 is emitted when the loop induction variable
    // or the loop bounds are not signed 32-bit numbers (int 
    // or long). Resolve this by changing the type of the 
    // induction variable.

#pragma loop(hint_parallel(0))
    for (unsigned int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

void code_1008()
{
    // Code 1008 is emitted when the compiler detects that
    // this loop does not perform enough work to warrant 
    // auto-parallelization.

    // You can resolve this by specifying the hint_parallel
    // pragma. CAUTION -- if the loop does not perform
    // enough work, parallelizing might cause a potentially 
    // large performance penalty.

    // #pragma loop(hint_parallel(0)) //  hint_parallel will force this through
    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

int A[1000];
void code_1009()
{
    // Code 1009 is emitted when the compiler tries to parallelize a 
    // "do-while" loop. The auto-parallelizer only targets "for" loops.

    int i = 0;
#pragma loop(hint_parallel(0))
    do
    {
        A[i] = A[i] + 1;
    } 
    while (++i < 1000);
}

JJ658585.collapse_all(ja-jp,VS.110).gif110x

X の 110 の理由コードが自動 vectorizer に適用されます。

理由コード

説明

1100

ループはフロー例のコントロールを、「または「または」含まれています。

1101

ループは変換が vectorized である必要があり、暗黙的なデータ型が含まれます。

1102

ループは、算術演算子やそのほかの非 vectorizable 操作が含まれます。

1103

ループ本体は、サイズがループ内で異なる可能性があるシフト演算が含まれます。

1104

ループ本体には、スカラー変数が含まれています。

1105

ループが認識されないリダクション演算が含まれます。

1106

内側のループが既に vectorized です。また、外側のループを vectorize できません

void code_1100(int *A, int x) 
{
    // Code 1100 is emitted when the compiler detects control flow
    // in the loop - for example, "if", the ternary operator "?", and
    // the like. Resolve this by flattening or removing control
    // flow in the loop body.

    // Not all control flow causes 1100; some is indeed  
    // vectorized.

    for (int i=0; i<1000; ++i)
    {
        // straightline code is more amenable to vectorization
        if (x)
        {
            A[i] = A[i] + 1;
        }
    }
}

void code_1101(int *A, char *B)
{
    // Code 1101 is emitted when the compiler is unable to vectorize
    // convert operations in the loop body. Many C/C++ conversions
    // are implicit. 

    // In this example, the 1-byte load of "B[i]" is converted to 4 bytes
    // prior to the addition by "1". The compiler, although able to 
    // vectorize most conversions, does not vectorize char -> int 
    // conversions.

    // Resolve this by eliminating conversions where possible.

    for (int i=0; i<1000; ++i)
    {
        A[i] = B[i] + 1;
    }
}

extern "C"  long _InterlockedExchange(long * Target, long Value);
void code_1102(int *A, long *x)
{
    // Code 1102 is emitted when the compiler is unable to vectorize
    // an operation in the loop body. For example, intrinsics and other
    // non-arithmetic, non-logical, and non-memory operations are not
    // vectorizable.

    // Resolve this by removing as many non-vectorizable operations
    // as possible from the loop body.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + _InterlockedExchange(x, 1);
    }
}

void code_1103(int *A, int *B)
{
    // Code 1103 is emitted when the compiler is unable to vectorize
    // a "shift" operation. In this example, there are two shifts
    // that cannot be vectorized.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] >> B[i]; // not vectorizable

        int x = B[i];
        A[i] = A[i] >> x; // not vectorizable
    }

    // To resolve this, ensure that your shift amounts are loop 
    // invariant. If the shift amounts cannot be loop invariant,
    // it may not be possible to vectorize this loop.

    int x = B[0];
    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] >> x; // vectorizable
    }
}

int code_1104(int *A, int *B)
{
    // When it vectorizes a loop, the compiler must 'expand' scalar
    // variables to a vector size such that they can fit in
    // vector registers. Code 1104 is emitted when the compiler
    // cannot 'expand' such scalars.

    // In this example, we try to 'expand' x to be used in the 
    // vectorized loop. However, there is a use of 'x' 
    // beyond the loop body, which prohibits this expansion.

    // To resolve this, try to limit scalars to be used only in
    // the loop body and not beyond, and try to keep their types
    // consistent with the loop types.

    int x;
    for (int i=0; i<1000; ++i)
    {
        x = B[i];
        A[i] = A[i] + x;
    }

    return x;
}

int code_1105(int *A)
{
    // The compiler performs an optimization that's known as "reduction"
    // when it operates on each element of an array and computes
    // a resulting scalar value - for example, in this piece of code, which
    // computes the sum of each element in the array:

    int s = 0;
    for (int i=0; i<1000; ++i)
    {
        s += A[i]; // vectorizable
    }

    // The reduction pattern must resemble the loop in the example. The
    // compiler emits code 1105 if it cannot deduce the reduction
    // pattern, as shown in this example:

    for (int i=0; i<1000; ++i)
    {
        s += A[i] + s;  // code 1105
    }

    // Similarly, reductions of "float" or "double" types require
    // that the /fp:fast switch is thrown. Strictly speaking,
    // the reduction optimization that the compiler performs uses
    // "floating point reassociation". Reassociation is only
    // allowed when /fp:fast is thrown.

    return s;    
}

void code_1106(int *A)
{
    // Code 1106 is emitted when the compiler tries to vectorize
    // an outer loop.

    for (int i=0; i<1000; ++i) // this loop is not vectorized
    {
        for (int j=0; j<1000; ++j) // this loop is vectorized
        {
            A[j] = A[j] + 1;
        }
    }
}

JJ658585.collapse_all(ja-jp,VS.110).gif120x

X の 120 の理由コードが自動 vectorizer に適用されます。

理由コード

説明

1200

ループは、ベクター化を防ぐループ データ変換のリンクが含まれています。ループの各反復で相互にこのようなデータの依存がないとループを vectorizing な答えを誤って生成、自動 vectorizer が自身に検証できないように干渉します。

1201

配列のベースへは、ループの中に変更します。

1202

構造体のフィールドは、32 または 64 の bit ではありません。

1203

ループ本体は配列に非連続のアクセスが含まれます。

void fn();
void code_1200(int *A)
{
    // Code 1200 is emitted when data dependence is prohibiting
    // vectorization. This can only be resolved by rewriting the
    // loop, and considering the marking of loop function calls as 
    // __forceinline.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i-1] + 1; // vectorization-prohibiting
        fn();               // vectorization-prohibiting
    }
}

void code_1201(int *A)
{
    // Code 1201 is emitted when an array base changes
    // in the loop body. Resolve this by rewriting your
    // code so that varying the array base is not necessary.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
        A++;
    }
}

typedef struct S_1202
{
    short a;
    short b;
} S_1202;

void code_1202(S_1202 *s)
{
    // Code 1202 is emitted when non-vectorizable struct accesses
    // are present in the loop body. Only struct accesses 
    // that are 32 or 64 bits are vectorized.

    for (int i=0; i<1000; ++i)
    {        
        s[i].a = s[i].b + 1; // this 16 bit struct access is not vectorizable
    }
}

void code_1203(int *A)
{
    // Code 1203 is emitted when non-vectorizable memory references
    // are present in the loop body. Vectorization of some non-contiguous 
    // memory access is supported - for example, the gather/scatter pattern.

    for (int i=0; i<1000; ++i)
    {
        A[i] += A[0] + 1;       // constant memory access not vectorized
        A[i] += A[i*2+2] + 2;  // non-contiguous memory access not vectorized
    }
}

JJ658585.collapse_all(ja-jp,VS.110).gif130x

X の 130 の理由コードが自動 vectorizer に適用されます。

理由コード

説明

1300

ループ本体は、非常に計算または小さ含まれています。

1301

ループのストライドは +1.ではありません。

1302

ループは「と」です。

1303

値を提供するベクター化のための十分なループ反復。

1304

ループは異なるサイズである割り当てが含まれます。

1305

完全が情報を入力する必要はありません。

void code_1300(int *A, int *B)
{
    // Code 1300 is emitted when the compiler detects that there is
    // no computation in the loop body.

    for (int i=0; i<1000; ++i)
    {
        A[i] = B[i]; // Do not vectorize, instead emit memcpy
    }
}

void code_1301(int *A)
{
    // Code 1301 is emitted when the stride of a loop is not positive 1.
    // Only loops that have a stride of positive 1 are vectorized;
    // rewriting your loop may be required.

    for (int i=0; i<1000; i += 2)
    {
        A[i] = A[i] + 1;
    }
}

void code_1302(int *A)
{
    // Code 1302 is emitted for "do-while" loops. Only "while"  
    // and "for" loops are vectorized.

    int i = 0;
    do
    {
        A[i] = A[i] + 1;
    } while (++i < 1000);
}

int code_1303(int *A, int *B)
{
    // Code 1303 is emitted when the compiler detects that
    // the number of iterations of the loop is too small to
    // make vectorization profitable.

    // If the loop computation fits perfectly in 
    // vector registers - for example, the upperbound is 4, or 8 in 
    // this case - then the loop _may_ be vectorized.

    // This loop is not vectorized because there are 5 iterations

    for (int i=0; i<5; ++i)
    {
        A[i] = A[i] + 1;
    }

    // This loop is vectorized

    for (int i=0; i<4; ++i)
    {
        A[i] = A[i] + 1;
    }

    // This loop is not vectorized because runtime pointer checks
    // are required to check that A and B don't overlap. It is not
    // worth it to vectorize this loop.

    for (int i=0; i<4; ++i)
    {
        A[i] = B[i] + 1;
    }

    // This loop is not vectorized because of the scalar reduction.

    int s = 0;
    for (int i=0; i<4; ++i)
    {
        s += A[i];
    }
    return s;
}

void code_1304(int *A, short *B)
{
    // Code 1304 is emitted when the compiler detects
    // different sized statements in the loop body.
    // In this case, there is an 32-bit statement and a
    // 16-bit statement.

    // In cases like this consider splitting the loop into loops to 
    // maximize vector register utilization.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
        B[i] = B[i] + 1;
    }
}

typedef struct S_1305
{
    int a;
    int b;
} S_1305;

void code_1305( S_1305 *s, S_1305 x)
{
    // Code 1305 is emitted when the compiler can't discern
    // proper vectorizable type information for this loop.
    // This includes non-scalar loop types such as struct 
    // assignments, as in this example.

    // Resolve this by ensuring that your loops have statements
    // that operate on integers or floating point types.

    for (int i=0; i<1000; ++i)
    {
        s[i] = x;
    }
}

JJ658585.collapse_all(ja-jp,VS.110).gif140x

X の 140 の理由コードは自動ベクター化と互換性がないオプションが指定されたと見なされます。

理由コード

説明

1400

#pragma loop(no_vector) を指定します。

1401

/kernel スイッチが指定されます。

1402

/arch:IA32 スイッチが指定されます。

1403

/arch:ATOM スイッチが指定され、ループは二つの操作が含まれます。

1404

/O1/Os スイッチが指定されます。

void code_1400(int *A)
{
    // Code 1400 is emitted when the no_vector pragma 
    // is specified. 

#pragma loop(no_vector)
    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

// Compile with /kernel
void code_1401(int *A)
{
    // Code 1401 is emitted when /kernel is specified.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

// Compile with /arch:IA32
void code_1402(int *A)
{
    // Code 1401 is emitted when /arch:IA32 is specified.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

// Compile with /favor:ATOM
void code_1403(double *A)
{
    // Code 1401 is emitted when /favor:ATOM is specified, and
    // the loop contains operations on "double" arrays.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

// Compile with /O1 or /Os
void code_1404(int *A)
{
    // Code 1401 is emitted when compiling for size.

    for (int i=0; i<1000; ++i)
    {
        A[i] = A[i] + 1;
    }
}

JJ658585.collapse_all(ja-jp,VS.110).gif150x

X の 150 の理由コード ブロックをエイリアシングに適用されます。エイリアシングは、メモリの位置を 2 回の名前でアクセスできる場合に発生します。

理由コード

説明

1500

多次元配列のできるエイリアシング。

1501

配列の構造体のできるエイリアシング。

1502

エイリアシングと可能な配列のインデックスは、以外の n + K.あります。

1503

エイリアシングと可能な配列のインデックスに複数のオフセットがあります。

1504

エイリアシングできる; 多すぎるランタイムのチェックが必要です。

1505

エイリアシングできる、ランタイムの検査は複雑すぎるです。

void code_1500(int A[100][100], int B[100][100])
{
    // Code 1500 is emitted when runtime pointer
    // disambiguation checks are required, and 
    // there are multidimensional array references.

    for (int i=0; i<100; ++i)
    {
        for (int j=0; j<100; ++j)
        {
            A[i][j] = B[i][j] + 1;
        }
    }
}

typedef struct S_1501
{
    int a;
    int b;
} S_1501;

void code_1501(S_1501 *s1, S_1501 *s2)
{
    // Code 1501 is emitted when runtime pointer
    // disambiguation checks are required, and 
    // there are array-of-struct accesses in the 
    // loop body.

    for (int i=0; i<100; ++i)
    {
        s1[i].a = s2[i].b + 1;
    }
}

void code_1502(int *A, int *B)
{
    // Code 1502 is emitted when runtime pointer
    // disambiguation checks are required, and 
    // an array reference has an offset that varies 
    // in the loop.

    int x = 0;
    for (int i=0; i<100; ++i)
    {
        A[i] = B[i + x] + 1;
        ++x;                   // 'x' varies in the loop
    }
}

void code_1503(int *A, int *B, int x, int y)
{
    // Code 1503 is emitted when runtime pointer
    // disambiguation checks are required, and 
    // an array reference has multiple offsets.

    for (int i=0; i<100; ++i)
    {
        A[i] = B[i+x] + B[i+y] + 1;   // multiple offsets when addressing 'B': {x, y}
        A[i] = B[i+x] + B[i] + 1;     // multiple offsets when addressing 'B': {x, 0}
        A[i] = B[i+x] + B[i+x] + 1;   // this is vectorized
    }
}

void code_1504(int *A1, int *A2, int *A3, int *A4, 
               int *A5, int *A6, int *A7, int *A8,
               int *A9, int *A10, int *A11, int *A12,
               int *A13, int *A14, int *A15, int *A16)
{
    // Code 1504 is emitted when too many runtime 
    // pointer disambiguation checks are required.

    for (int i=0; i<100; ++i)
    {
        ++A1[i];
        ++A2[i];
        ++A3[i];
        ++A4[i];
        ++A5[i];
        ++A6[i];
        ++A7[i];
        ++A8[i];
        ++A9[i];
        ++A10[i];
        ++A11[i];
        ++A12[i];
        ++A13[i];
        ++A14[i];
        ++A15[i];
        ++A16[i];
    }
}

void code_1505(int *A, int *B)
{
    // Code 1505 is emitted when runtime pointer 
    // disambiguation checks are required, but are
    // too complex for the compiler to discern.

    for (int i=0; i<100; ++i)
    {
        for (int j=0; j<100; ++j)
        {
            for (int k=0; k<100; ++k)
            {
                A[i+j-k] = B[i-j+k] + 1;
            }
        }
    }
}

参照

関連項目

自動並列のエラーおよび警告

#pragma loop()

/Q オプション (低水準の操作)

/Qpar-report (Auto-Parallelizer Reporting Level)

/Qvec-report (Auto-Vectorizer Reporting Level)

その他の技術情報

ネイティブ コードでの並列プログラミング