Floating point opencl内核浮动4问题

Floating point opencl内核浮动4问题,floating-point,opencl,jocl,Floating Point,Opencl,Jocl,我正在研究Fruchtermon和Reingold布局算法的OpenCL实现,与我已经实现的CPU版本相比,它几乎可以正常工作。然而,我注意到,对于大型图,排斥函数有一个瓶颈——它计算图中每对顶点之间的排斥力。我决定尝试使用OpenCLfloat4结构来减少这个瓶颈,但结果好坏参半 我已经设置了代码,以便可以使用float4,而实际上只使用1个位置进行调试。当我只使用一个单位置float_workers=1时,该功能正常工作 然而,当我将float_workers设置为>1时,我的行为变得越来越

我正在研究Fruchtermon和Reingold布局算法的OpenCL实现,与我已经实现的CPU版本相比,它几乎可以正常工作。然而,我注意到,对于大型图,排斥函数有一个瓶颈——它计算图中每对顶点之间的排斥力。我决定尝试使用OpenCLfloat4结构来减少这个瓶颈,但结果好坏参半

我已经设置了代码,以便可以使用float4,而实际上只使用1个位置进行调试。当我只使用一个单位置float_workers=1时,该功能正常工作

然而,当我将float_workers设置为>1时,我的行为变得越来越古怪。

我不知道我的代码出了什么问题-我使用的是JOCL,因为整个内核都在我的Java类中的一个字符串中,所以像:gid*=+string.valueoffload_+这样的行;一定要有意义,并编译

行标记1至2根据浮动工人设置浮动4,项目数量为1至4项。当float_workers=1时,此循环将GID映射到一对节点;当float_workers较高时,此循环将GID映射到两对、三对或四对节点。线标记2到3是正在执行的实际工作,用于计算排斥节点的量。线标记3到端点将结果设置为置换数组,因此稍后可以更新节点的位置。显然,当我将内核放入队列时,我正确地调整了工作进程的数量,所以这似乎不是问题所在

我假设每个XPO[…]只能设置一次,对吗?这是我能想到的唯一能打破这一切的东西。我错过什么了吗

__kernel void repel(__global const float *optDist,
          __global const int *nIndexes,
          __global const float *xPos,
          __global const float *yPos,
          __global float *xDisp,
          __global float *yDisp,
          __global int *nodes, +
          __global int *startIndexes,
          __global int* totalWork){
             int sub = nodes[0] - 1;
             int work_dim = get_work_dim();
             int gid = 0;
             for(int i = 0; i < work_dim - 1; i++){
               gid += get_global_id(i) * get_global_size(i);
             }
             gid += get_global_id(work_dim - 1);
             gid *= " + String.valueOf(float_workers) + ";
             int gid_start = gid;
             if(gid >= totalWork[0]){return;}
             int v,u,i;
             v = u = i = 0;
             float4 xDelta = (float4)(0.0f,0.0f,0.0f,0.0f); 
             float4 yDelta = (float4)(0.0f,0.0f,0.0f,0.0f);
             int found = 0;
             (1)for(i = 0; i < nodes[0]; i++){
               if(found == " + String.valueOf(float_workers) + "){
                 break;
               }
               if(gid < startIndexes[i]){
                 v = i - 1;
                 u = (gid - startIndexes[i - 1]) + 1;
                 gid ++;
                 i--;
                 if(found == 0){
                   xDelta.s0 = xPos[v] - xPos[u];
                   yDelta.s0 = yPos[v] - yPos[u];
                 }
                 if(found == 1){
                   xDelta.s1 = xPos[v] - xPos[u];
                   yDelta.s1 = yPos[v] - yPos[u];
                 }
                 if(found == 2){
                   xDelta.s2 = xPos[v] - xPos[u];
                   yDelta.s2 = yPos[v] - yPos[u];
                 }
                 if(found == 3){
                   xDelta.s3 = xPos[v] - xPos[u];
                   yDelta.s3 = yPos[v] - yPos[u];
                 }
                 found++;
               }
             }
             (2)
             float4 deltaLength = sqrt((xDelta * xDelta) + (yDelta * yDelta));
             float4 _optDist = (float4)(optDist[0], optDist[0], optDist[0], optDist[0]);
             float4 force = _optDist / deltaLength;
             float4 xResult = (xDelta / deltaLength) * force;
             float4 yResult = (yDelta / deltaLength) * force;
             (3)
             if ((xDelta.s0 == 0) && (yDelta.s0 == 0)) {
               xDisp[gid_start + 0] = 0;
               yDisp[gid_start + 0] = 0;
             }
             else{
               xDisp[gid_start + 0] = xResult.s0;
               yDisp[gid_start + 0] = yResult.s0;
             }
             if(" + String.valueOf(float_workers) + " > 1){
               if ((xDelta.s1 == 0) && (yDelta.s1 == 0)) {
                 xDisp[gid_start + 1] = 0;
                 yDisp[gid_start + 1] = 0;
               }
               else{
                 xDisp[gid_start + 1] = xResult.s1;
                 yDisp[gid_start + 1] = yResult.s1;
               }
             }
             if(" + String.valueOf(float_workers) + " > 2){
               if ((xDelta.s2 == 0) && (yDelta.s2 == 0)) {
                 xDisp[gid_start + 2] = 0;
                 yDisp[gid_start + 2] = 0;
               }
               else{
                 xDisp[gid_start + 2] = xResult.s2;
                 yDisp[gid_start + 2] = yResult.s2;
                 }
             }
             if(" + String.valueOf(float_workers) + " > 3){
               if ((xDelta.s3 == 0) && (yDelta.s3 == 0)) {
                 xDisp[gid_start + 3] = 0;
                 yDisp[gid_start + 3] = 0;
               }
               else{
                 xDisp[gid_start + 3] = xResult.s3;
                 yDisp[gid_start + 3] = yResult.s3;
               }
             }
    }

如果xDelta.s1==0&&yDelta.s1==0浮点值很少等于零,您的意思是接近零还是精确零?尝试使用容差。我会明确地检查这一点,但无论我使用的是单个浮点值4,还是多个浮点值4,都不会大致相同吗?使用浮点值4除了语法之外,没有什么特别的好处,例如,如果您将它们用于read_imagef中的RGBA图像数据。最后一个使用速度更快的硬件是AMD的vector VLIW4/5硬件。新的GCN硬件是标量的。即使生成SSE的英特尔CPU编译器在矢量化矢量代码之前也会对其进行标量化。@Dithermaster有趣的是,我仍然想知道为什么代码会与float4一起中断,但听起来我应该恢复为常规的float?