2016-03-23 5 views
2

OpenCLでIsing Modelのシミュレーションを構築しています。これは、データが/ 1または/ -1。OpenCL - バイトを8要素のベクトルに分割する最も効率的な方法

メモリ帯域幅を節約するために、これらの状態の8つが1バイト(1 = 0、1 = 0)にエンコードされます。計算の1つでは、元の状態、すなわち1または-1に対応する値を持つ整数ベクトルが必要です。

例:
入力バイト(OpenCLの中UCHAR):01010011
変換するには:(int8)(-1,1,-1,1,-1,-1,1,1);

私はその問題のための実用的なソリューションを持っているが、より速く、より効率的があれば、私は思ったんだけど方法:

uchar c = spins[id]; 
int8 spin; 
spin.s0 = (c >> 0) & 1; 
spin.s1 = (c >> 1) & 1; 
spin.s2 = (c >> 2) & 1; 
spin.s3 = (c >> 3) & 1; 
spin.s4 = (c >> 4) & 1; 
spin.s5 = (c >> 5) & 1; 
spin.s6 = (c >> 6) & 1; 
spin.s7 = (c >> 7) & 1; 
spin = spin * 2 - 1; 

EDIT:

が速く私の状況ではしていないようですが、それはのLEAでより簡潔ですt:

__constant uchar8 bits = (uchar8)(0,1,2,3,4,5,6,7); 

uchar c = spins[id]; 
int8 spin = convert_int8((uchar8)(c) >> bits & 1) * 2 - 1; 
+0

これはすでに非常にうまくいっているようですが、なぜもっと複雑なものに行くのですか? 'int8 spin =((int8)(c)>>(int8)(0,1,2,3,4,5,6,7)&1)* 2 - 1;' – DarkZeros

答えて

1

bool8はまだ予約されているタイプです。私はそれがユーザーのために開いていると思った、私は間違っている。

オプション1)すべてのハードウェアに取り組んでいますが、カーネルで、その後

  typedef union hardwareBool8{ 
       char v; 
       bool bit_select[8]; 
      } vecb8; 

この組合を定義することができます(100%を確認してください)

安全でもない:

  vecb8 t={5}; // initialize with any number from your uchar/char 
      t.v=1; // or initialize with this 
      t.bit_select[4]=0; // set or get to some integer 
      int intVariable =t.bit_select[7]; // can be 1 or 0 or -1,you should try. If not -1 then you can negate 
      int intVariable2=-t.bit_select[7]; 

これは私のamdマシンでコンパイルしていますが、他のハードウェアについてはわかりません。 エンディアンも問題になります。

オプション2)

たぶん8つのスレッド(又は8つのスレッドから同じ場所にアクセスすること)に同じ文字を放送:

:各スレッドに異なるビット率で作業

char charVar= ... load from same address/index ; 

...

spin.s7 = (c >> 7) & 1; (on thread 7) 

は、単一のスピン要素に対してのみパフォーマンスを提供する必要があります。多くの最新のgpuアーキテクチャは、単一の命令ですべてのスレッドに同じデータをブロードキャストすることをサポートしています。お使いのデバイスがCPUの場合、ワークグループあたり8つのスレッドがあまり遅くないはずですが、gpuの場合、連続する8つのスレッドにつき1つの文字を選択するのは難しいです。

charArrayIndex = globalThreadId/8 
    c = charArray[charArrayIndex]; 

    // assuming spin is local memory array and shared by work group threads 
    spin[globalThreadId % 8] = (c >> (globalThreadId % 8)) & 1; 

ような何かスピンはプライベート変数であることを持っている場合、あなたはすべてのスレッドのプライベート変数に値をコピーする通信配列と同一のローカルメモリ・アレイを使用することができます。これは、(命令レベル+スレッドレベル)の並列処理からスレッドレベルの並列処理までです。

オプション3)

操作は、これは、注文実行のうちの利益を得ることができる別の単位で行われる場合は、異なる「ユニット」コアのにビット選択(それらの全8)を分配することができます。

spin.s2 = (c/4) & 1; // 1 division and 1 logical 
spin.s0 = (c) & 1;  // 1 logical 
spin.s1 = (c & 2)>0; // 1 logical and 1 comparison 
+0

ありがとう!私は本当に第3のものを得ていない。 – Gigo

+0

高価ですが独立した方法でスピン要素を取得し、重い作業を計算する間、他の要素は命令レベルの並列性を使用して計算されます。また、最後の要素は、 "と" 1を必要としません。なぜなら、右側には単一のビットしかないからです。あなたはこのように別の命令を保存します。 –

+0

私は、この場合、組合を使用しているとは思わない。それは私のマシン(AMDも)でコンパイルされますが、奇妙な結果をもたらします。私はboolがおそらく単なるビット幅ではないので、バイトのアドレッシングをこのようにすることはできないと思います。 – Gigo

関連する問題