2

タスクは、C 整数配列の各要素をその絶対値に設定することです。できるだけ効率的に行うようにしています。以下は、私が行った最適化の進行です。これらが実際に最適化なのかどうか、さらにできることがあれば教えてください!

関数の最初のパラメーターは整数配列になり、2 番目はその配列の整数サイズになります。

標準的な実装は次のとおりです。

void absolute (int array[], int n){
  for(int i = 0; i < n; i++)
    if(array[i] < 0)
      array[i] = - array[i];
}

入門プログラミング コースの教授を満足させるにはこれで十分ですが、もう少し試して、途中で最適化について何か学びたいと思います。

https://stackoverflow.com/a/2074403に基づく、ブランチレスの絶対値:

void absolute (int array[], int n){
  for(int i = 0; i < n; i++){
    uint32_t temp = array[i] >> 31;     // make a mask of the sign bit
    array[i] ^= temp;                   // toggle the bits if value is negative
    array[i] += temp & 1;               // add one if value was negative
  }
}

ゼロとの比較がより効率的であり、余分な変数を配置する必要がないことに基づいています。

void absolute (int array[], int n){
  for(n--; n >= 0;){
    uint32_t temp = array[n] >> 31;
    array[n] ^= temp;
    array[n] += temp & 1;
  }
}

(これはもうベクトル化されますか?)

それは私が得た限りです。この機能を最適化するためにさらにできることはありますか?

4

2 に答える 2

3

最高のパフォーマンスを得るには、 SIMD命令を使用することをお勧めします。
プロセッサが異なれば、サポートされる SIMD 命令のセットも異なります。

  • x86 にはMMXSSEAVXなどがあります。
  • ARM にはNEON SIMD アクセラレータがあります。
  • PowerPC にはAltiVecがあります。

手動 SIMD 命令の最適化を使用する一般的な方法は、C組み込み関数によるものです。

次の例では、SSE 組み込みを使用しています。

#include <intrin.h>

//Limitations:
//1. n must be a multiple of 4.
void absolute(const int array[], int n)
{
    int x;

    //Process 4 elements per iteration.
    for (x = 0; x < n; x += 4)
    {  
        __m128i a3_a2_a1_a0 = _mm_loadu_si128((__m128i*)&array[x]);     //Load 4 int32 elements from array.

        a3_a2_a1_a0 = _mm_abs_epi32(a3_a2_a1_a0);                       //Set absolute of 4 int32 elements in single instruction.

        _mm_storeu_si128((__m128i*)(&array[x]), a3_a2_a1_a0);           //Store 4 int32 elements of array.
    }
}

考慮してください: これは単なる例です (最高のパフォーマンスの最高ではありません)。

私のコードサンプルを測定してくれてありがとう、ブランドン。

于 2016-07-15T08:43:15.227 に答える