2016-11-17 73 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] 
} 

讓我們假設主機是小端,但設備是big endian和A,B,C,是彩車:

  • 將b和加載非標準化的垃圾?

    • 如果是的話,我是否必須發送一個字節來告訴內核緩衝區endianness?
    • 如果沒有,都轉換的(使用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; 
          } 

         } 

,因爲它正在爲我的英特爾iGPU的與目前英特爾CPU和其它機器採用AMD CPU和AMD的GPU不任何字節序問題。未來如果我在英特爾CPU之上獲得Nvidia gpu和AMD GPU?

Ofcourse在集羣計算,需要涵蓋計算機,但關於其他操作系統上運行,並使用相同設備的虛擬操作系統之間有什麼字節順序的情況?那麼該設備是一個具有多個排序核心(可能?)的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我個人不知道任何。 –