Cuda 推力中的sort_by_键是阻塞调用吗?
我反复将一系列内核排队:Cuda 推力中的sort_by_键是阻塞调用吗?,cuda,gpgpu,thrust,Cuda,Gpgpu,Thrust,我反复将一系列内核排队: for 1..100: for 1..10000: // Enqueue GPU kernels Kernel 1 - update each element of array Kernel 2 - sort array Kernel 3 - operate on array end // run some CPU code output "Waiting for
for 1..100:
for 1..10000:
// Enqueue GPU kernels
Kernel 1 - update each element of array
Kernel 2 - sort array
Kernel 3 - operate on array
end
// run some CPU code
output "Waiting for GPU to finish"
// copy from device to host
cudaMemcpy ... D2H(array)
end
内核3的阶数是O(N^2),因此是迄今为止最慢的。对于内核2,我直接在设备上使用推力::按密钥排序:
thrust::device_ptr<unsigned int> key(dKey);
thrust::device_ptr<unsigned int> value(dValue);
thrust::sort_by_key(key,key+N,value);
推力::装置ptr键(dKey);
推力:装置的ptr值(D值);
推力::按_键对_排序(键,键+N,值);
这个对推力的调用似乎是阻塞的,因为CPU代码只有在内部循环完成后才能执行。我之所以看到这一点,是因为如果我删除对sort\u by_key
的调用,主机代码(正确)会在内部循环完成之前输出“Waiting”字符串,而如果我运行排序,则不会输出
有没有一种方法可以异步调用<代码>推力::按\u键排序
首先考虑有一个内核启动队列,它只能容纳这么多未决的发射。一旦启动队列已满,其他任何类型的内核启动都会被阻塞。在空队列槽可用之前,主机线程将不会继续(超出这些启动请求)。我敢肯定,在达到10000次迭代之前,3次内核发布的10000次迭代将填满这个队列。因此,如果您按顺序启动30000个内核,那么任何类型的非平凡内核启动都会有一些延迟(我认为)。(但是,最终,当所有内核都被添加到队列中时,因为有些内核已经完成了,如果没有其他阻塞行为,那么在所有内核实际完成之前,您将看到“waiting…”消息。)
推力::按键排序
(大小约等于数据集大小)。每次使用时,都会通过cudamaloc
操作在引擎盖下分配临时存储。此cudamaloc
操作被阻塞。当从主机线程启动cudamaloc
时,它会等待内核活动出现间隙,然后才能继续cudamaloc
行为。(但见下文讨论)据我所知,推力方法(1,上面)仍然会在每次迭代中有效地执行某种临时分配/空闲步骤,即使您提供了自定义分配器。如果您有一个设计良好的自定义分配器,那么这可能几乎是一个“无操作”。cub方法似乎有一个缺点,即需要知道最大大小(以便完全消除分配/空闲步骤的需要),但我认为对于推力自定义分配器也会有相同的要求。否则,如果您需要在某个时候分配更多内存,那么定制分配器实际上必须执行类似于
cudamaloc
的操作,这将给工作带来麻烦。嗨,罗伯特,谢谢!我不知道那个小熊。我现在可以预先分配临时存储。这甚至可能带来性能提升,尽管可能不会太多。队列大小将是我没有考虑的问题。我想知道是否有办法查询设备的最大队列大小……我不相信有办法查询队列大小(或可用插槽数)。据我所知,这不是一个出版数量。如果您愿意的话,编写一个程序来发现它是什么并不困难(至少大致如此)。但是,它可能会因设备而异,甚至可能因CUDA版本而异。