2016-11-17 14 views
0

gpu、cpu、およびカスタマイズされたopenclチップ間の精度/精度/位置合わせの不一致を除いて、インターネット上のすべてのopenclサンプルがホスト側バッファを直接受け入れる理由は何ですか?OpenCLデバイスのエンディアン

clEnqueueWriteBuffer ( cl_command_queue command, ...) 

__kernel void vecAdd(__global float * c, ..) 
{ 
    int id=get_global_id(0); 
    c[id]=b[id]+a[id] 
} 

ホストとさせて頂きますリトルエンディアンですが、デバイスはビッグエンディアンであり、a、b、cは、浮動小数点数です:

  • はbのだろうと、非正規化されたゴミとして読み込むこと?

    • もしそうなら、バッファエンディアンについてカーネルに伝える1バイトを送信する必要がありますか?
    • もしそうでなければ、自動的にバッファ読取り/書込み操作の間に(CPUの4バイトSIMDシャッフルまたはGPUでの変換を使用して)変換されますか? USE_HOST_PTR(RAM)タイプのバッファとCL_MEM_READ_WRITE(GDDR)についても?
    • 未知の場合、下の例の関数は常に動作しますか?以下のようなカーネルを助けるために

      int endianness_of_device() 
          { 
            unsigned int x = 1; 
            return (( ( (char *)&x) [0])==0?0:1) ; 
          } 
      
          int reverseBytesInt(int bytes) 
          { 
           void * p = &bytes; 
           uchar4 bytesr = ((uchar4 *)p)[0].wzyx; 
           int * p2=(int *)&bytesr; 
           return *p2; 
          } 
      
          float reverseBytesFloat(float bytes) 
          { 
           void * p = &bytes; 
           uchar4 bytesr = ((uchar4 *)p)[0].wzyx; 
           float * p2=(float *)&bytesr; 
           return *p2; 
          } 
      
          uint sizeOf2(uint structSize) 
          { 
           uit mult0=structSize/256;mult0++; 
           return mult0*256; 
          } 
      
          typedef struct 
          { 
           uchar end; 
           uchar sizeRelByteAdr; 
           uchar adrRelByteAdr; 
           uchar idRelByteAdr; 
           uchar valRelByteAdr; 
           uchar woRelByteAdr; 
           int size; 
           uint adr; 
           int id; 
           float val; 
           float wo; 
          }nn_p_n; 
      
      
      
      
          uint malloc(__global uchar * heap, __global uint * mallocCtr, int size) 
          { 
           return (atomic_add(mallocCtr,(uint)size)+(uint)heap); 
          } 
      

  __kernel void nn(__global uchar *heap,__global uint * mallocCtr) 
         { 
          int id=get_global_id(0); 
          if(id==0) 
          { 

           nn_p_n * np=(nn_p_n *)malloc(heap,mallocCtr,sizeOf2(sizeof(nn_p_n))); 
           np->end=endianness_of_device(); 
           np->size=sizeOf2(sizeof(nn_p_n)); 
           np->id=9; 
           np->val=99.9f; 

           // lets simulate different endianness 
           np->end=1-endianness_of_device(); 


           np->adr=(uint)np-(uint)heap; 

           mem_fence(CLK_GLOBAL_MEM_FENCE); 
          } 

          if(id==900) 
          { 
           // simulating another device reads buffer 
           for(int i=0;i<1000000;i++){int dummy=0; dummy++; if(dummy>id) dummy++;} 

           nn_p_n n=*((nn_p_n *)&heap[0]); 
           if(n.end!=endianness_of_device()) 
           { 
            n.size=reverseBytesInt(n.size); 
            //if(n.size!=sizeof2(sizeof(nn_p_n))) 
            //{ return; } 
            n.adr=reverseBytesInt(n.adr); 
            n.val=reverseBytesFloat(n.val); 
           } 
           nn_p_n * np=(nn_p_n *)malloc(heap,mallocCtr,sizeOf2(sizeof(nn_p_n))); 
           *np = n; 
          } 

         } 

それは、AMDのCPUとAMDのGPUを搭載したIntelの現時点でCPUや他のマシンなしで自分のインテルigpuのために働いているので、エンディアンの問題。将来、Intel CPUの上にNvidia gpuとAmd gpuをインストールするとどうなりますか?

クラスタコンピューティングではもちろん、コンピュータ間のエンディアンケースをカバーする必要がありますが、仮想OSは別のOSで動作し、同じデバイスを使用していますか?そのデバイスは、複数のエンディアン・コアを持つFPGAです(可能ですか?)。

最後の質問:?OSの力のすべてのデバイスでもCPUは、同じエンディアンになることができ

編集(私はそうは思いませんが、パフォーマンスを犠牲にOSによってエミュレートされるだろうか?):それはデバイス側で読み取り専用データを前処理することは不可能です。ホスト側では、「書き込み済み」とマークされた要素を後処理するのは面倒ですが、データ全体がギガバイトでホストにダウンロードされる一方、1-2要素しか書き込まれない可能性があるためです。

+0

@ Gundolf Gundelfingerによると、完璧なコードはありません、完璧なハードウェアのセットアップがあります。 –

答えて

1

カーネルに渡される引数は、正しいエンディアン(したがってすべてのtypedefs cl_intなど)を持つことが保証されていますが、これはバッファには当てはまりません。バッファの内容はOpenCLでは完全に不透明であるため、これは意味があります。ユーザは、内部の内容を理解する方法を知っているだけです。したがって、(おそらく専用のカーネルを起動することによって)計算を行う前に潜在的なエンディアン変換を実行するのはユーザーの責任です。

すなわち:ここ

__kernel void vecAdd(__global float * c, ..) 

cは、(ポインタのバイト自体が正しいデバイス順である)正しいエンディアンであることが保証されているが、バイトが指さcは、ユーザーがホスト上で設定した順序に関係なくあります。

インターネット上のすべてのopenclの例が、ホスト側のバッファを直接受け入れるのはなぜですか?

ほとんどのプログラムは、特性があらかじめわかっている非常に狭いターゲットプラットフォームで開発されています。すべてがリトルエンディアンの場合、ビッグエンディアンをサポートするのはどうしてですか?移植性はすでに難しい問題です。エンディアンを気にすることは、一般的なケースでは、付加価値のほとんどない大きな複雑さです。大多数のプログラムではそれだけの価値はありません。

このような移植性の高さを考える価値がある場合は、実装するのはあなたの選択です。

+0

私は同意します。ホストのエンディアンと一致しないOpenCLデバイスの実例もありますか? – Dithermaster

+0

@Dithermaster私は個人的には何も知らない。 –