2016-07-28 99 views
1

我已經使用OpenCL成功實現了數字下變換器。在實現插值部分時,我只能設置146的最大因子。任何一個都會導致程序崩潰並引發錯誤代碼CL_INVALID_MEM_OBJECT -38使用太多內存的OpenCL程序

對於那些不知道的人來說,插值是一種在已知數據點範圍內構建新數據點的方法。 DDC或數字下變頻器用於在嘗試通過重構濾波器重建數據點時增加或減少採樣率。

請注意,我正在使用的文件是1.75Mb的wav文件作爲輸入。它的採樣頻率爲44100,我的目標是以48000採樣(藍光質量)。這導致160/147的插值/抽取因子。但是,超過146的任何插值因素會導致驅動程序和程序崩潰,並且如上所示拋出-38的錯誤。

我認爲問題在於我創建了cl_mem緩衝區。我大概有7個,這裏是他們如何初始化和使用。假設P爲3且Q是2,而項數是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的因素,仍然很多!)我怎麼能把這個下降?我是否以不正確的方式使用緩衝區?

最重要的是,我有三個主機代碼中的其他內存分配。 'Array'只是保存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))); 

以下是Visual Studio中P = 3時的內存使用情況(數組增加3的大小)。

enter image description here

這裏就是我得到的-38碼writeBuffers之一。

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; 

}

EDIT發生 錯誤,因爲緩衝區大小我分配有超過所使用的存儲器的512Mb。這是我可以擁有的最大緩衝區大小。爲了解決這個問題,我必須在我的代碼中實現某種內存管理系統。也許一次使用8Mb緩衝區。

+0

你能告訴我們你寫入這些緩衝區的位置以及你調用內核的地方嗎? (並且清理代碼也可能是個好主意)'CL_INVALID_MEM_OBJECT'我認爲不會被'clCreateBuffer'拋出。 – JavaProphet

+0

@JavaProphet我已經添加了writeBuffer以及內核。它也爲decimate內核拋出相同的錯誤。我會嘗試添加發生錯誤時輸出的日誌消息。 – VedhaR

回答

0

你的記憶對象沒有明確的任何支持,這可能是你的問題。我建議把一個標誌添加從

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

CL_MEM_USE_HOST_PTRCL_MEM_COPY_HOST_PTR,或CL_MEM_ALLOC_HOST_PTR,然後指定主機指針。如果使用CL_MEM_USE_HOST_PTR,那麼如果主機內存中的緩衝區不會再次分配給主機,那麼如果它只是內存使用情況,可能會幫助您解決問題。

+0

所以我試着用'CL_MEM_COPY_HOST_PTR'來處理你的方法,看起來性能很慢。我首先嚐試了它的輸入緩衝區,並注意到Interpolate內核跳了13ms。然後,當我嘗試輸出緩衝區相同,程序崩潰。內插內核只是一個簡單的內核,它在給定輸入數組的每個'n'位置添加一個元素。 – VedhaR

+0

@VedhaR我不推薦'CL_MEM_COPY_HOST_PTR',但是'CL_MEM_USE_HOST_PTR'。 – JavaProphet

+0

對不起,這就是我的意思,我用'CL_MEM_USE_HOST_PTR',我只是把它錯誤地複製到這裏的框中 – VedhaR