不同的结果GPU&每组超过8个工作项时的CPU

时间:2015-11-04 15:57:22

标签: opencl

我是open cl的新人。并且尝试编写代码来检查许多折线与单个多边形之间的交叉点。

我在cpu和gpu中运行代码..并得到不同的结果。

首先,我在调用NULL时将local作为clEnqueueNDRangeKernel参数发送。

clEnqueueNDRangeKernel(command_queue, kIntersect, 1, NULL, &global, null, 2, &evtCalcBounds, &evtKernel);

在尝试了许多事情之后,我看到如果我发送1作为本地,它运作良好。并为cpu和gpu返回相同的结果。

size_t local = 1;
clEnqueueNDRangeKernel(command_queue, kIntersect, 1, NULL, &global, &local, 2, &evtCalcBounds, &evtKernel);

更多地玩abit并发现当我运行带有本地8或更多的内核(由于某种原因)时,cpu返回false结果。

我没有使用任何本地内存,只是全局和私有。

我没有添加代码,因为我认为它与问题无关(请注意,对于单个工作组而言,它工作正常),并且它很长。如果需要,我会尝试简化它。

代码流程如下:

我有一个存储在大缓冲区中的折线坐标。而另一个中的单个多边形。另外,我提供了另一个带有单个int的缓冲区,用于保存当前结果计数。所有缓冲区都是__global个参数。

在内核中,我只需检查" polyline[get_global(0)]"的所有行之间的交集。用polygon的行。如果是真的, 我使用atomic_inc进行结果计数。没有来自同一缓冲区的读写内存,没有障碍或内存,... atomic_inc是我使用的唯一线程安全机制。

- 更新 -

添加了我的代码:

我知道我可以更好地使用open cl函数来计算一些向量,但是现在,我只是将代码从旧的常规CPU单线程程序转换为CL。所以这不是我现在关注的问题。

bool isPointInPolygon(float x, float y, __global float* polygon) {
    bool blnInside = false;
    uint length = convert_uint(polygon[4]);
    int s = 5;
    uint j = length - 1;
    for (uint i = 0; i < length; j = i++) {
        uint realIdx = s + i * 2;
        uint realInvIdx = s + j * 2;
        if (((polygon[realIdx + 1] > y) != (polygon[realInvIdx + 1] > y)) &&
            (x < (polygon[realInvIdx] - polygon[realIdx]) * (y - polygon[realIdx + 1]) / (polygon[realInvIdx + 1] - polygon[realIdx + 1]) + polygon[realIdx]))
            blnInside = !blnInside;
    }
    return blnInside;
}

bool isRectanglesIntersected(float p_dblMinX1, float p_dblMinY1,
    float p_dblMaxX1, float p_dblMaxY1,
    float p_dblMinX2, float p_dblMinY2,
    float p_dblMaxX2, float p_dblMaxY2) {
    bool blnResult = true;

    if (p_dblMinX1 > p_dblMaxX2 ||
        p_dblMaxX1 < p_dblMinX2 ||
        p_dblMinY1 > p_dblMaxY2 ||
        p_dblMaxY1 < p_dblMinY2) {
        blnResult = false;
    }

    return blnResult;
}

bool isLinesIntersects(
    double Ax, double Ay,
    double Bx, double By,
    double Cx, double Cy,
    double Dx, double Dy) {

    double  distAB, theCos, theSin, newX, ABpos;

    //  Fail if either line is undefined.
    if (Ax == Bx && Ay == By || Cx == Dx && Cy == Dy) 
        return false;

    //  (1) Translate the system so that point A is on the origin.
    Bx -= Ax; By -= Ay;
    Cx -= Ax; Cy -= Ay;
    Dx -= Ax; Dy -= Ay;

    //  Discover the length of segment A-B.
    distAB = sqrt(Bx*Bx + By*By);

    //  (2) Rotate the system so that point B is on the positive X axis.
    theCos = Bx / distAB;
    theSin = By / distAB;
    newX = Cx*theCos + Cy*theSin;
    Cy = Cy*theCos - Cx*theSin; Cx = newX;
    newX = Dx*theCos + Dy*theSin;
    Dy = Dy*theCos - Dx*theSin; Dx = newX;

    //  Fail if the lines are parallel.
    return (Cy != Dy);
}

bool isPolygonInersectsPolyline(__global float* polygon, __global float* polylines, uint startIdx) {

    uint polylineLength = convert_uint(polylines[startIdx]);
    uint start = startIdx + 1;

    float x1 = polylines[start];
    float y1 = polylines[start + 1];
    float x2;
    float y2;

    int polygonLength = convert_uint(polygon[4]);
    int polygonLength2 = polygonLength * 2;
    int startPolygonIdx = 5;

    for (int currPolyineIdx = 0; currPolyineIdx < polylineLength - 1; currPolyineIdx++)
    {
        x2 = polylines[start + (currPolyineIdx*2) + 2];
        y2 = polylines[start + (currPolyineIdx*2) + 3];

        float polyX1 = polygon[0];
        float polyY1 = polygon[1];
        for (int currPolygonIdx = 0; currPolygonIdx < polygonLength; ++currPolygonIdx)
        {
            float polyX2 = polygon[startPolygonIdx + (currPolygonIdx * 2 + 2) % polygonLength2];
            float polyY2 = polygon[startPolygonIdx + (currPolygonIdx * 2 + 3) % polygonLength2];

            if (isLinesIntersects(x1, y1, x2, y2, polyX1, polyY1, polyX2, polyY2)) {
                return true;
            }

            polyX1 = polyX2;
            polyY1 = polyY2;
        }

        x1 = x2;
        y1 = y2;
    }

    // No intersection found till now so we check containing
    return isPointInPolygon(x1, y1, polygon);
}

__kernel void calcIntersections(__global float* polylines, // My flat points array - [pntCount, x,y,x,y,...., pntCount, x,y,... ]
                    __global float* pBounds, // The rectangle bounds of each polyline - set of 4 values [top, left, bottom, right....]
                    __global uint* pStarts, // The start index of each polyline in the polylines array
                    __global float* polygon, // The polygon i want to intersect with - first 4 items are the rectangle bounds [top, left, bottom, right, pntCount, x,y,x,y,x,y....]
                    __global float* output, // Result array for saving the intersections polylines indices
                    __global uint* resCount) // The result count
{
    int i = get_global_id(0);
    uint start = convert_uint(pStarts[i]);

    if (isRectanglesIntersected(pBounds[i * 4], pBounds[i * 4 + 1], pBounds[i * 4 + 2], pBounds[i * 4 + 3],
        polygon[0], polygon[1], polygon[2], polygon[3])) {

        if (isPolygonInersectsPolyline(polygon, polylines, start)){
            int oldVal = atomic_inc(resCount);
            output[oldVal] = i;
        }
    }   
}

有人可以向我解释一下吗?

0 个答案:

没有答案