主机以 CPU 台设备结束之前未完成的任务
Incomplete task before HOST ends with CPU device
我只有一个 CPU 具有两个内核的 Core i3,所以我只能使用 CPU,而不是 GPU。我想使用带有简单添加内核的 OpenCL 来测试一个简单示例。但这是我的问题:
分配平台、CPU设备等后,我执行以下操作:
1) clEnqueueNDRange() 将一个内核任务排入队列,并使用最后一个参数为该任务的完成分配一个事件。
2) 使用 CL_COMPLETE 的 clSetEventCallback() 将回调函数链接到上述事件。
正常情况下,回调函数应该在任务完成时调用。但事实并非如此。事实上,如果主机在结束之前还有很多事情要做,那么结束事件中的任务就结束了。有人能告诉我为什么吗?
这是我的最小代码:
/** Simple add kernel */
private static String programSource0 =
"__kernel void vectorAdd(" +
" __global const float *a,"+
" __global const float *b, " +
" __global float *c)"+
"{"+
" int gid = get_global_id(0);"+
" c[gid] = a[gid]+b[gid];"+
"}";
/** The entry point of this sample */
public static void main(String args[])
{
/** Callback function */
EventCallbackFunction kernelCommandEvent = new EventCallbackFunction()
{
@Override
public void function(cl_event event, int event_status, Object user_data)
{
System.out.println("Callback: task COMPLETED");
}
};
// Initialize the input data
int n = 1000000;
float srcArrayA[] = new float[n];
float srcArrayB[] = new float[n];
float dstArray0[] = new float[n];
Array.fill(srcArrayA, 1,0f);
Array.fill(srcArrayB, 1,0f);
// .
// (hidden) Allocation of my Intel platform, CPU device, kernel, commandQueue, and memory buffer, set the argument to kernel etc...
// .
// Set work-item dimensions and execute the kernels
long globalWorkSize[] = new long[]{n};
// I pass an event on completion of the command queue.
cl_event[] myEventID = new cl_event[1];
myEventID[0] = new cl_event();
clEnqueueNDRangeKernel(commandQueue, kernel0, 1, null, globalWorkSize, null, 0, null, myEventID[0]);
// I link the event to the callback function "kernelCommandEvent", and pass 10 as parameter
clSetEventCallback(myEventID[0], CL_COMPLETE, kernelCommandEvent, new Integer(10));
// host does some very long stuff !!
// Normally, my device task should be completed
int[] ok = new int[1];
Arrays.fill(ok, 0);
clGetEventInfo(myEventID[0], CL_EVENT_COMMAND_EXECUTION_STATUS, Sizeof.cl_int, Pointer.to(ok), null);
if (ok[0] == CL_COMPLETE) System.out.println("Task COMPLETE");else System.out.println("Task INCOMPLETE");
}
Enqueue 不强制执行任务。它只是将其放入队列中。
只有在以下情况下才会执行任务:
- 使用
clFlush()
强制立即执行。
- 进行直接或间接依赖于该任务的阻塞调用。
有些司机还可以决定他们将开始处理某项任务,即使您没有刷新它也是如此。但这取决于实现。如果你想确定使用 clFlush(commandQueue);
额外:
这种行为是这样的,因为将数据排队到设备的开销可能很大,如果在循环中多次调用,则每次 Enqueue 调用都执行此操作可能效率不高。相反,它被推迟到刷新或阻塞调用,因此它可以被批处理。
我只有一个 CPU 具有两个内核的 Core i3,所以我只能使用 CPU,而不是 GPU。我想使用带有简单添加内核的 OpenCL 来测试一个简单示例。但这是我的问题:
分配平台、CPU设备等后,我执行以下操作:
1) clEnqueueNDRange() 将一个内核任务排入队列,并使用最后一个参数为该任务的完成分配一个事件。
2) 使用 CL_COMPLETE 的 clSetEventCallback() 将回调函数链接到上述事件。
正常情况下,回调函数应该在任务完成时调用。但事实并非如此。事实上,如果主机在结束之前还有很多事情要做,那么结束事件中的任务就结束了。有人能告诉我为什么吗?
这是我的最小代码:
/** Simple add kernel */
private static String programSource0 =
"__kernel void vectorAdd(" +
" __global const float *a,"+
" __global const float *b, " +
" __global float *c)"+
"{"+
" int gid = get_global_id(0);"+
" c[gid] = a[gid]+b[gid];"+
"}";
/** The entry point of this sample */
public static void main(String args[])
{
/** Callback function */
EventCallbackFunction kernelCommandEvent = new EventCallbackFunction()
{
@Override
public void function(cl_event event, int event_status, Object user_data)
{
System.out.println("Callback: task COMPLETED");
}
};
// Initialize the input data
int n = 1000000;
float srcArrayA[] = new float[n];
float srcArrayB[] = new float[n];
float dstArray0[] = new float[n];
Array.fill(srcArrayA, 1,0f);
Array.fill(srcArrayB, 1,0f);
// .
// (hidden) Allocation of my Intel platform, CPU device, kernel, commandQueue, and memory buffer, set the argument to kernel etc...
// .
// Set work-item dimensions and execute the kernels
long globalWorkSize[] = new long[]{n};
// I pass an event on completion of the command queue.
cl_event[] myEventID = new cl_event[1];
myEventID[0] = new cl_event();
clEnqueueNDRangeKernel(commandQueue, kernel0, 1, null, globalWorkSize, null, 0, null, myEventID[0]);
// I link the event to the callback function "kernelCommandEvent", and pass 10 as parameter
clSetEventCallback(myEventID[0], CL_COMPLETE, kernelCommandEvent, new Integer(10));
// host does some very long stuff !!
// Normally, my device task should be completed
int[] ok = new int[1];
Arrays.fill(ok, 0);
clGetEventInfo(myEventID[0], CL_EVENT_COMMAND_EXECUTION_STATUS, Sizeof.cl_int, Pointer.to(ok), null);
if (ok[0] == CL_COMPLETE) System.out.println("Task COMPLETE");else System.out.println("Task INCOMPLETE");
}
Enqueue 不强制执行任务。它只是将其放入队列中。
只有在以下情况下才会执行任务:
- 使用
clFlush()
强制立即执行。 - 进行直接或间接依赖于该任务的阻塞调用。
有些司机还可以决定他们将开始处理某项任务,即使您没有刷新它也是如此。但这取决于实现。如果你想确定使用 clFlush(commandQueue);
额外: 这种行为是这样的,因为将数据排队到设备的开销可能很大,如果在循环中多次调用,则每次 Enqueue 调用都执行此操作可能效率不高。相反,它被推迟到刷新或阻塞调用,因此它可以被批处理。