ベクトル化診断を使用してコードを調整し、パフォーマンスを改善する

コンパイラから、ベクトル化による最適化が適用された場所およびベクトル化を適用できなかった場所を示す診断情報が提供されます。この情報を取得するためのコマンドラインオプションは、--diag_warning=optimizations および --remarks です。

Example 16 に、配列に単純な累計演算を実装した 2 つの関数を示します。このコードはベクトル化されません。

Example 16. ベクトル化不可能なコード

int addition(int a, int b)
{
    return a + b;
}
void add_int(int *pa, int *pb, unsigned int n, int x)
{
    unsigned int i;
    for(i = 0; i < n; i++) *(pa + i) = addition(*(pb + i),x);
    /* 関数呼び出しはベクトル化できない */
}

--diag_warning=optimizations オプションを使用すると、addition() 関数の最適化の警告メッセージが表示されます。--remarks の場合も同様です。

__inline 修飾子を addition() の定義に追加するとこのコードをベクトル化できますが、まだ最適化されていません。--diag_warning=optimizations オプションを再度使用すると、ループがベクトル化されたがポインタのエイリアスの生成の問題が存在する可能性があるという最適化の警告メッセージが表示されます。--remarks の場合も同様です。

コンパイラは、エイリアス生成のランタイムテストを生成し、コードのベクトル化されたコピーとスカラのコピーの両方を出力する必要があります。Example 17 に、ポイントのエイリアスが生成されていないことがわかっている場合に restrict キーワードを使用して改善できる方法を示します。

Example 17. restrict を使用したベクトル化パフォーマンスの向上

__inline int addition(int a, int b)
{
    return a + b;
}
void add_int(int * __restrict pa, int * __restrict pb, unsigned int n, int x)
{
    unsigned int i;
    for(i = 0; i < n; i++) *(pa + i) = addition(*(pb + i),x);
}

最後に、ループの繰り返し回数に対して改善を行うことが出来ます。Example 17 では、繰り返し回数は定まっておらず、NEON レジスタに正確に適合する倍数でない可能性があります。すなわち、ベクトル化されていないコードを使用して実行するために残りの繰り返しをテストする必要があります。繰り返し回数が NEON でサポートされる繰り返し回数のいずれかであることがわかっている場合は、そのことをコンパイラに指示できます。Example 18に、ベクトル化によって最高のパフォーマンスを得るための最終的な改善を示します。

Example 18. ベクトル化のパフォーマンスを最適にするために調整されたコード

__inline int addition(int a, int b)
{
    return a + b;
}
void add_int(int * __restrict pa, int * __restrict pb, unsigned int n, int x)
{
    unsigned int i;
    __promise((n % 4) == 0);
    /* n は 4 の倍数 */
    for(i = 0; i < (n & ~3); i++) *(pa + i) = addition(*(pb + i),x);    
}

Show/hide関連項目

Copyright © 2010 ARM. All rights reserved.ARM DUI 0472BJ
Non-ConfidentialID011811