Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory management OpenCL的问题_Memory Management_Opencl - Fatal编程技术网

Memory management OpenCL的问题

Memory management OpenCL的问题,memory-management,opencl,Memory Management,Opencl,我正面临OpenCL的一个问题,我希望有人能对可能的原因有所提示。下面是一个版本的程序,简化为问题。我有一个大小为4000的输入int数组。在我的内核中,我正在进行扫描。显然,有很好的并行方法来实现这一点,但是为了重现问题,只有一个线程在执行整个计算。在扫描之前,输入(结果屏蔽)只有值0或1 __kernel void sel_a(__global db_tuple * input, __global int * result_mask, __global int * r

我正面临OpenCL的一个问题,我希望有人能对可能的原因有所提示。下面是一个版本的程序,简化为问题。我有一个大小为4000的输入int数组。在我的内核中,我正在进行扫描。显然,有很好的并行方法来实现这一点,但是为了重现问题,只有一个线程在执行整个计算。在扫描之前,输入(结果屏蔽)只有值0或1

__kernel void
sel_a(__global db_tuple * input,
      __global int * result_mask,
      __global int * result_count,
      const unsigned int max_id)
{
// update mask based on input in parallel

mem_fence(CLK_GLOBAL_MEM_FENCE);

if(gid == 0)
{
    int i, c = 0;
    for(i = 0; i < max_id; i++)
    {
        if(result_mask[i]!=0)
        {
            c++;
            result_mask[i] = 5;
        }
        else
        {
            result_mask[i] = 5;
        }
    }
    *result_count = c;
}
}
我在大约3200个元素之后的某个地方得到了这个由80个元素组成的块。它不总是相同的位置,但它总是相同数量的元素-80。更奇怪的是,如果我把第一行改成 如果(gid==2000) 问题已经解决了。然而,在使用线程id之后,我得出结论,问题并没有消失,它只是移动了。使用线程1425,我有一半的时间会遇到问题,当我遇到问题时,buggy block位于数组的末尾。因此,我假设,当我没有0和1时,块已经“向后移动”了。更令人兴奋的是,当我将输入大小增加到5000时,输出完全由0组成。此外,以下代码不起作用:

if(gid == 0)
{
    int i, c = 0;
    for(i = 0; i < max_id; i++)
    {
        if(result_mask[i]!=0)
        {
            c++;
            result_mask[i] = 5;
        }
        else
        {
            result_mask[i] = 5;
        }
    }
    *result_count = c;
}
if(gid == 3999)
{
    int i, c = 0;
    for(i = 0; i < max_id; i++)
    {
        if(result_mask[i]!=0)
        {
            c++;
            result_mask[i] = 5;
        }
        else
        {
            result_mask[i] = 5;
        }
    }
    *result_count = c;
}
显然,我错过了一些重要的事情。我的第一个想法是内存冲突,80个元素的块被另一个“线程”覆盖。但是我想得越多,它就越没有意义

如果有任何提示,我将不胜感激! 谢谢

编辑: 很抱歉反应太晚。因此,我修改了代码,将其减少到最低限度以重现问题。以下是程序的c代码:

#include <stdio.h>
#include <stdlib.h>

#include <OpenCL/openCL.h>

#define INPUTSIZE (200)

typedef struct tag_openCL
{
    cl_device_id        device;

    cl_context          ctx;
    cl_command_queue    queue;
    cl_program          program;
} openCL;

int main(void)
{
    int err;
    openCL* cl_ctx = malloc(sizeof(openCL));

    if(!cl_ctx)
        exit(1);

    err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &cl_ctx->device, NULL);

    cl_ctx->ctx = clCreateContext(0, 1, &cl_ctx->device, clLogMessagesToStdoutAPPLE, NULL, &err);

    cl_ctx->queue = clCreateCommandQueue(cl_ctx->ctx, cl_ctx->device, CL_QUEUE_PROFILING_ENABLE, &err);

    printf("Successfully created context and queue for openCL device. \n");

    /* Build program */

    char * kernel_source = "__kernel void \
sel(__global int * input, \
    __global int * result_mask, \
    const unsigned int max_id) \
{ \
    int gid = get_global_id(0); \
    \
    result_mask[gid] = input[gid] % 2 == 0; \
    result_mask[gid] &= (input[gid] + 1) % 3 == 0; \
    \
    if(gid == 0) { \
        int i; \
        for(i = 0; i < max_id; i++) { \
            if(result_mask[i]) { \
                result_mask[i] = 5; \
            } \
            else { \
                result_mask[i] = 5; \
            } \
        } \
    } \
}";

    cl_program prog = clCreateProgramWithSource(cl_ctx->ctx, 1, (const char**)&kernel_source, NULL, &err);
    cl_ctx->program = prog;

    err = clBuildProgram(cl_ctx->program, 0, NULL, NULL, NULL, NULL);

    cl_kernel kernel = clCreateKernel(cl_ctx->program, "sel", &err);

    /* create dummy input data */
    int * input = calloc(sizeof(int), INPUTSIZE);
    int k;
    for(k = 0; k < INPUTSIZE; k++)
    {
        input[k] = abs((k % 5) - (k % 3))+ k % 2;
    }

    cl_mem source, intermediate;

    unsigned int problem_size = INPUTSIZE;

    source = clCreateBuffer(cl_ctx->ctx, CL_MEM_READ_WRITE, problem_size * sizeof(int), NULL, NULL);
    clEnqueueWriteBuffer(cl_ctx->queue, source, CL_TRUE, 0, problem_size * sizeof(int), (void*) input, 0, NULL, NULL);

    intermediate = clCreateBuffer(cl_ctx->ctx, CL_MEM_READ_WRITE, problem_size * sizeof(int), NULL, NULL);

    int arg = 0;
    clSetKernelArg(kernel, arg++, sizeof(cl_mem), &source);
    clSetKernelArg(kernel, arg++, sizeof(cl_mem), &intermediate);
    clSetKernelArg(kernel, arg++, sizeof(unsigned int), &problem_size);

    size_t global_work_size = problem_size;
    size_t local_work_size = 1;
    clEnqueueNDRangeKernel(cl_ctx->queue, kernel, 1, NULL, &global_work_size, &local_work_size, 0, NULL, NULL);

    clFinish(cl_ctx->queue);

    // read results
    int * result = calloc(sizeof(int), problem_size );
    clEnqueueReadBuffer(cl_ctx->queue, intermediate, CL_TRUE, 0, problem_size * sizeof(int), result, 0, NULL, NULL);
    clFinish(cl_ctx->queue);


    int j;
    for(j=1; j<=problem_size; j++)
    {
        printf("%i \t", result[j-1]);
        if(j%10 ==0 && j>0)
            printf("\n");
    }

    return EXIT_SUCCESS;
}
#包括
#包括
#包括
#定义输入大小(200)
typedef结构标记\u openCL
{
cl_设备\u id设备;
cl_上下文ctx;
cl_命令_队列;
CLU计划;
}openCL;
内部主(空)
{
INTERR;
openCL*cl_ctx=malloc(sizeof(openCL));
如果(!cl_ctx)
出口(1);
err=CLGetDeviceID(NULL,CL\U设备类型\U GPU,1,&CL\U ctx->DEVICE,NULL);
cl_ctx->ctx=clCreateContext(0,1,&cl_ctx->device,cllogmessagestostdoutaple,NULL,&err);
cl\u ctx->queue=clCreateCommandQueue(cl\u ctx->ctx,cl\u ctx->device,cl\u queue\u PROFILING\u ENABLE,&err);
printf(“为openCL设备成功创建了上下文和队列。\n”);
/*构建程序*/
char*kernel\u source=“\uu kernel void\
sel(全局整数*输入\
__全局整数*结果掩码\
常量无符号整数(最大id)\
{ \
int gid=获取全局id(0)\
\
结果屏蔽[gid]=输入[gid]%2==0\
结果屏蔽[gid]&=(输入[gid]+1)%3==0\
\
如果(gid==0){\
int i\
对于(i=0;ictx,1,(const char**)和kernel_source,NULL和err);
cl_ctx->program=prog;
err=clBuildProgram(cl_ctx->program,0,NULL,NULL,NULL);
cl_kernel kernel=clCreateKernel(cl_ctx->program,“sel”、&err);
/*创建虚拟输入数据*/
int*input=calloc(sizeof(int),INPUTSIZE);
int k;
对于(k=0;kctx,cl_MEM_READ_WRITE,problem_size*sizeof(int),NULL,NULL);
clEnqueueWriteBuffer(cl_ctx->queue,source,cl_TRUE,0,problem_size*sizeof(int),(void*)输入,0,NULL,NULL);
中间=clCreateBuffer(cl_ctx->ctx,cl_MEM_READ_WRITE,problem_size*sizeof(int),NULL,NULL);
int arg=0;
clSetKernelArg(kernel、arg++、sizeof(cl_mem)和source);
clSetKernelArg(kernel、arg++、sizeof(cl_mem)和mediate);
clSetKernelArg(kernel、arg++、sizeof(unsigned int)和problem_size);
大小\u t全局\u工作\u大小=问题大小;
大小\u t本地工作\u大小=1;
clEnqueueNDRangeKernel(cl_ctx->queue,kernel,1,NULL,&global_-work_-size,&local_-work_-size,0,NULL,NULL);
clFinish(cl_ctx->队列);
//读取结果
int*result=calloc(sizeof(int),问题大小);
clenqueueredbuffer(cl_ctx->queue,intermediate,cl_TRUE,0,problem_size*sizeof(int),result,0,NULL,NULL);
clFinish(cl_ctx->队列);
int j;
对于(j=1;j0)
printf(“\n”);
}
返回退出成功;
}
结果仍然是不确定的,我在输出中的随机位置得到0和1。对于大小为1的本地工作组,它们位于数组的上半部分,对于大小为2的本地工作组,在下半部分,对于大小为4的本地工作组,可以容纳200个元素,但对于大小为400的问题,同样存在0和1。此外,对于大小为1的全局工作组,所有工作都正常。也就是说,如果我使用两个内核,一个用于并行计算,全局工作组大小为[problem size],另一个用于并行计算,全局工作组大小为1,那么一切都很好。再一次,我非常清楚这不是实现它的方法(一个运行这种顺序代码的内核),但是,我想知道为什么它不工作,因为看起来我遗漏了一些东西

谢谢,
Vassil

您的OpenCL代码非常简单,结果非常奇怪。我认为问题可能来自安装部分。创建缓冲区、调用EnqueueNDRange等。您可以发布设置部分吗?我想问题可能就在那里

编辑: 在看到您的代码并对其进行测试之后,我意识到最初我并没有完全理解您的问题。当你提到面具更新部分的时候,我的脑子里已经摆脱了那句台词。我第一次应该能答对

问题是无法同步不同的工作组。CLK_GLOBAL_MEM_围栏影响工作组的内存顺序访问(确保在回读之前完成对全局内存的写入)
if(gid == 3999)
{
    int i, c = 0;
    for(i = 0; i < max_id; i++)
    {
        if(result_mask[i]!=0)
        {
            c++;
            result_mask[i] = 5;
        }
        else
        {
            result_mask[i] = 5;
        }
    }
    *result_count = c;
}
Device name: GeForce 9600M GT
Device vendor: NVIDIA
    Clock frequency:        1250 MHz
    Max compute units:      4
    Global memory size:     256 MB
    Local memory size:.     16 KB
    Max memory allocation size: 128 MB
    Max work group size:        512 
#include <stdio.h>
#include <stdlib.h>

#include <OpenCL/openCL.h>

#define INPUTSIZE (200)

typedef struct tag_openCL
{
    cl_device_id        device;

    cl_context          ctx;
    cl_command_queue    queue;
    cl_program          program;
} openCL;

int main(void)
{
    int err;
    openCL* cl_ctx = malloc(sizeof(openCL));

    if(!cl_ctx)
        exit(1);

    err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &cl_ctx->device, NULL);

    cl_ctx->ctx = clCreateContext(0, 1, &cl_ctx->device, clLogMessagesToStdoutAPPLE, NULL, &err);

    cl_ctx->queue = clCreateCommandQueue(cl_ctx->ctx, cl_ctx->device, CL_QUEUE_PROFILING_ENABLE, &err);

    printf("Successfully created context and queue for openCL device. \n");

    /* Build program */

    char * kernel_source = "__kernel void \
sel(__global int * input, \
    __global int * result_mask, \
    const unsigned int max_id) \
{ \
    int gid = get_global_id(0); \
    \
    result_mask[gid] = input[gid] % 2 == 0; \
    result_mask[gid] &= (input[gid] + 1) % 3 == 0; \
    \
    if(gid == 0) { \
        int i; \
        for(i = 0; i < max_id; i++) { \
            if(result_mask[i]) { \
                result_mask[i] = 5; \
            } \
            else { \
                result_mask[i] = 5; \
            } \
        } \
    } \
}";

    cl_program prog = clCreateProgramWithSource(cl_ctx->ctx, 1, (const char**)&kernel_source, NULL, &err);
    cl_ctx->program = prog;

    err = clBuildProgram(cl_ctx->program, 0, NULL, NULL, NULL, NULL);

    cl_kernel kernel = clCreateKernel(cl_ctx->program, "sel", &err);

    /* create dummy input data */
    int * input = calloc(sizeof(int), INPUTSIZE);
    int k;
    for(k = 0; k < INPUTSIZE; k++)
    {
        input[k] = abs((k % 5) - (k % 3))+ k % 2;
    }

    cl_mem source, intermediate;

    unsigned int problem_size = INPUTSIZE;

    source = clCreateBuffer(cl_ctx->ctx, CL_MEM_READ_WRITE, problem_size * sizeof(int), NULL, NULL);
    clEnqueueWriteBuffer(cl_ctx->queue, source, CL_TRUE, 0, problem_size * sizeof(int), (void*) input, 0, NULL, NULL);

    intermediate = clCreateBuffer(cl_ctx->ctx, CL_MEM_READ_WRITE, problem_size * sizeof(int), NULL, NULL);

    int arg = 0;
    clSetKernelArg(kernel, arg++, sizeof(cl_mem), &source);
    clSetKernelArg(kernel, arg++, sizeof(cl_mem), &intermediate);
    clSetKernelArg(kernel, arg++, sizeof(unsigned int), &problem_size);

    size_t global_work_size = problem_size;
    size_t local_work_size = 1;
    clEnqueueNDRangeKernel(cl_ctx->queue, kernel, 1, NULL, &global_work_size, &local_work_size, 0, NULL, NULL);

    clFinish(cl_ctx->queue);

    // read results
    int * result = calloc(sizeof(int), problem_size );
    clEnqueueReadBuffer(cl_ctx->queue, intermediate, CL_TRUE, 0, problem_size * sizeof(int), result, 0, NULL, NULL);
    clFinish(cl_ctx->queue);


    int j;
    for(j=1; j<=problem_size; j++)
    {
        printf("%i \t", result[j-1]);
        if(j%10 ==0 && j>0)
            printf("\n");
    }

    return EXIT_SUCCESS;
}