OpenCL程序使用太多内存

时间:2016-07-28 18:43:55

标签: c arrays memory opencl

我已经使用OpenCL成功实现了数字下变频器。实现插值部分时,我只能将最大因子设置为146.任何更多因素都会导致程序崩溃并抛出错误代码CL_INVALID_MEM_OBJECT -38

对于那些不了解的人来说,插值是一种在已知数据点范围内构建新数据点的方法。 DDC或数字下变频器用于在尝试使用重建滤波器重建数据点时提高或降低采样率。

请注意,我使用的文件是一个1.75Mb的wav文件作为输入。它的采样值为44100,我的目标是以48000(蓝光质量)进行采样。这导致插值/抽取因子为160/147。但是超过146的任何插值因子都会使驱动程序崩溃,并且如上所示抛出了-38的程序和错误。

我认为问题出在我创建cl_mem缓冲区的地方。我有大概7,这是他们如何初始化和使用。假设P为3且Q为2,而num_items为918222个样本:

input = clCreateBuffer(
    context,
    CL_MEM_READ_ONLY,
    num_items * sizeof(float),
    NULL,
    &status);

output = clCreateBuffer(
    context,
    CL_MEM_WRITE_ONLY,
    num_items * P * sizeof(float),
    NULL,
    &status);

//Lowpass kernel parameters
inputForLowpass = clCreateBuffer(
    context,
    CL_MEM_READ_ONLY,
    num_items * P * sizeof(float),
    NULL,
    &status);

outputFromLowpass = clCreateBuffer(
    context,
    CL_MEM_READ_ONLY,
    num_items * P * sizeof(float),
    NULL,
    &status);

//Decimate kernel parameters
inputForDecimate = clCreateBuffer(
    context,
    CL_MEM_READ_ONLY,
    num_items * P * sizeof(float),
    NULL,
    &status);

outputFromDecimate = clCreateBuffer(
    context,
    CL_MEM_READ_ONLY,
    (int)(num_items * (P*1.0 / Q) * sizeof(float)),
    NULL,
    &status);

//numOfCoefficients for number of taps
coeff = clCreateBuffer(
    context,
    CL_MEM_READ_ONLY,
    numOfCoefficients * sizeof(float),
    NULL,
    &status);

我在Visual Studio中使用内存调试器来发现程序使用602Mb(在崩溃之前插值因子为160.它使用了大约120Mb的因子3,还有很多!)我怎么能把它搞定?我是否以错误的方式使用缓冲区?

除此之外,我在主机代码中还有其他三个内存分配。 '阵列'只需保存wav文件中的值,而OutputData和OutputData2分别存储来自过滤输入和抽取输入的值。

Array = (float*)malloc(num_items * sizeof(float));
OutputData = (float*)malloc(num_items * P * sizeof(float));
OutputData2 = (float*)malloc((int)(num_items * (P*1.0 / Q) * sizeof(float)));

以下是当P = 3时,Visual Studio中内存使用情况的图像(数组增加3的大小)。

enter image description here

这是一个writeBuffers,我得到了-38代码。

status = clEnqueueWriteBuffer(
    cmdQueue,
    inputForLowpass,
    CL_FALSE,
    0,
    num_items * P * sizeof(float),
    OutputData,
    0,
    NULL,
    NULL);
printf("Input enqueueWriteBuffer for Lowpass Kernel status: %i \n", status);

这是低通内核:

__kernel void lowpass(__global float *Array, __global float *coefficients, __global float *Output, __const int numOfCoefficients) {

    int globalId = get_global_id(0); 
    float sum=0.0f;
    int min_i= max((numOfCoefficients-1),globalId)-(numOfCoefficients-1);
    int max_i= min_i+numOfCoefficients;
    for (int i=min_i; i< max_i; i++)
    {
        sum +=Array[i]*coefficients[globalId-i];    
    }
    //sum = min(., (0.999969482421875));
    //sum = max(sum, -1.0f);
    Output[globalId]=sum;

}

修改 发生错误是因为我分配的缓冲区大小使用了超过512Mb的内存。这是我可以拥有的缓冲区的最大大小。为了解决这个问题,我必须在我的代码中实现某种内存管理系统。也许一次使用8Mb缓冲区。

1 个答案:

答案 0 :(得分:0)

您的内存对象未被任何内容明确支持,这可能是您的问题。我建议从

添加一个标志

https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clCreateBuffer.html

,例如CL_MEM_USE_HOST_PTRCL_MEM_COPY_HOST_PTRCL_MEM_ALLOC_HOST_PTR,然后指定主机指针。如果使用CL_MEM_USE_HOST_PTR,如果缓冲区位于主机内存中,则不会再次在主机上分配缓冲区,如果它仅仅是内存使用,可能会帮助您解决问题。