2017-06-03 9 views
3

OpenCLでIntel CPU上の構造体の使用に関する質問があります。はるかに速く、私は次のようにカーネルを変更する場合Intel OpenCLコンパイラ:structの使用を最適化する

struct pair { 
    float first; 
    float second; 
}; 

inline const float f(const struct pair param) { 
    return param.first * param.second; 
} 

inline const struct pair access_func(__global float const * const a, __global float const * const b, const int i) { 
    struct pair res = { 
      a[i], 
      b[i] 
    }; 
    return res; 
} 

// slow 
__kernel ...(__global float const * const a, __global float const * const b) 
{ 
// ... 

x = f(access_func(a, b, i)); 

// ... 
} 

は、それが実行されます:

// fast 
__kernel ...(__global float const * const a, __global float const * const b) 
{ 
// ... 

x = a[i] * b[ i ]; 

// ... 
} 

インテルを聞かせする方法はあります私の現在のカーネルは、次のように構造体を使用して、2つのバッファにアクセスコンパイラはこの最適化を行いますか? NVIDIAコンパイラはこれを行うことができると思われます。なぜなら、私はGPU上のランタイムに違いは見られないからです。

ありがとうございます!

+0

これはconstであり、キャッシュ管理に大きな負荷をかけることができますか? –

+0

私は 'const'キーワードを削除しようとしましたが、それは問題を解決しませんでした。 –

答えて

0

コンパイラは、OpenCLデバイスとホスト間、および/またはOpenCLデバイス上の複数のカーネル間でバッファが共有されていることを考慮して、データのメモリレイアウトの最適化を実行できません。最も効率的なレイアウトは、カーネル内のアクセスパターンに依存し、各カーネルでは明らかに異なることがあります。

データのメモリレイアウトを賢明に選択する必要があります。これはGPUプログラミングの最も難しい部分の1つです。彼らが好むものを見つけるためには、それぞれの実装についてOpenCLの最適化ガイドを参照してください。場合によっては、メモリがglobalからメモリがlocalにコピーされ、ローカルコピーから作業することによって、非効率的なアクセスパターンがマスクされることがあります。

+1

私はバッファを共有していないが、問題は残っていることをコンパイラに知らせるために 'restrict'キーワードを追加しようとしました。私はメモリのレイアウトが重要であることを理解していますが、本当にここで問題になっていますか?私の質問で述べたように、問題はCPU上でのみ発生します。明らかに最適化はGPU上で行うことができます。 –

+0

x86 CPUは、 "水平"算術演算を行い、OpenCLコンパイラが一般的にコンパイルするものであるSIMD(SSE/AVX)を介した処理のために結果を適切にパックする必要があります。 GPUは基本的に基本的に構造が異なり、このような状況をうまく処理できるように設計されています。なぜなら、構造体配列の頂点バッファを持つのが一般的だからです。コンパイラはデータを並べ替えていないので、GPUはより効率的に処理します。 CPUは、配列の構造体のレイアウトでうまくいく。 (参照:SOA vs AOS) – pmdj

+0

私はちょうどチェックして、私はSSEまたはAVXで水平な乗算命令を見つけることができないので、その理由があります。コンパイラはおそらく、少なくとも乗算よりも多くの "アンパック"命令を生成しています。データレイアウトの問題! – pmdj

関連する問題