字节排列顺序OpenCL设备
除了一个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元可能已被写入这些元素,而整体数据可能是千兆字节下载到主机。
传递给内核的参数保证具有正确的字节顺序(因此所有typedefs cl_int
等),但缓冲区并非如此。这很有意义,因为缓冲区的内容对于OpenCL来说是完全不透明的:只有用户知道如何理解内部的内容。因此,在进行计算之前(可能通过启动专用内核),执行潜在字节序转换是用户的责任。
换句话说:
__kernel void vecAdd(__global float * c, ..)
这里,值的c
被保证是正确的字节序(指针的字节本身是在正确的设备顺序),但字节指向通过c
是为了什么用户设置他们的主机上。
为什么互联网上的所有opencl实例都直接接受主机端缓冲区?
大多数程序都是针对相对狭窄的目标平台进行开发的,其中的特征事先已知:如果它们都是小端,为什么要支持大端?可移植性已经是一个难题,而且我怀疑,在一般情况下,关心字节序的问题在增值很少的情况下会带来额外的复杂性。对绝大多数的程序来说这是不值得的。
如果您认为这种级别的可移植性很有价值,那么您可以选择实施它。
我同意。是否有一个真实世界的OpenCL设备示例与主机的字节序不匹配? – Dithermaster
@Dithermaster我个人不知道任何。 –
根据@Gundolf Gundelfinger,没有完美的代码,有完美的硬件设置。 –