CUDA是否为您自动实现负载平衡?
我希望得到一些关于CUDA C中负载平衡最佳实践的一般性建议和澄清,特别是:CUDA是否为您自动实现负载平衡?,cuda,load-balancing,gpgpu,Cuda,Load Balancing,Gpgpu,我希望得到一些关于CUDA C中负载平衡最佳实践的一般性建议和澄清,特别是: 如果一条经线中的一条线比另一条经线需要更长的时间,它会阻碍另一条经线的完成吗 如果是,是否将备用处理能力分配给另一个warp 为什么我们需要扭曲和阻塞的概念?在我看来,翘曲只是一小块32根线 一般来说,对于给定的内核调用,我需要什么样的负载平衡? 每个经纱中的线 每个块中的线程 所有块上的线程 最后,给出一个示例,您将为以下功能使用哪些负载平衡技术: 我有一个向量x0的N点:[1,2,3,…,N] 我随机选择5
- 如果一条经线中的一条线比另一条经线需要更长的时间,它会阻碍另一条经线的完成吗
- 如果是,是否将备用处理能力分配给另一个warp
- 为什么我们需要扭曲和阻塞的概念?在我看来,翘曲只是一小块32根线
- 一般来说,对于给定的内核调用,我需要什么样的负载平衡?
- 每个经纱中的线
- 每个块中的线程
- 所有块上的线程
x0
的N
点:[1,2,3,…,N]
x1
(例如[1,log(2),3,4,5,…,N]
)写入内存x1
上重复上述2个操作以产生x2
(例如[1,log(log(2)),3,4,log(5),…,N]
),然后再进行8次迭代以产生x3
<代码>x10x10
然而,使用GPU从全局内存中随机读取大面积数据并不是最有效的,因此您还应该考虑是否真的需要完全随机。线程分为三个不同的级别。Warps利用SIMD实现更高的计算密度。线程块利用多线程实现延迟容忍。网格为跨SMs的负载平衡提供独立的粗粒度工作单元 经线 硬件一起执行扭曲的32个线程。它可以使用不同的数据执行单个指令的32个实例。如果线程采用不同的控制流,因此它们并非都在执行同一条指令,那么在指令执行时,这32个执行资源中的一些将处于空闲状态。这在CUDA引用中称为控制分歧 如果内核表现出大量的控制差异,那么在这个级别重新分配工作可能是值得的。这通过使所有执行资源在一个扭曲中保持忙碌来平衡工作。您可以在线程之间重新分配工作,如下所示
// Identify which data should be processed
if (should_do_work(threadIdx.x)) {
int tmp_index = atomicAdd(&tmp_counter, 1);
tmp[tmp_index] = threadIdx.x;
}
__syncthreads();
// Assign that work to the first threads in the block
if (threadIdx.x < tmp_counter) {
int thread_index = tmp[threadIdx.x];
do_work(thread_index); // Thread threadIdx.x does work on behalf of thread tmp[threadIdx.x]
}
//确定应该处理哪些数据
如果(应该做什么工作(threadIdx.x)){
int tmp_索引=原子添加(&tmp_计数器,1);
tmp[tmp_index]=threadIdx.x;
}
__同步线程();
//将该工作分配给块中的第一个线程
if(螺纹IDX.x
块中的翘曲
在SM上,硬件将计划扭曲到执行单元上。有些指令需要一段时间才能完成,因此调度程序会交错执行多个扭曲,以使执行单元保持忙碌。如果某些扭曲尚未准备好执行,将跳过它们,而不会造成性能损失
在这个级别上通常不需要负载平衡。只需确保每个线程块有足够的扭曲可用,以便调度器始终可以找到准备好执行的扭曲
网格中的块
运行时系统将块调度到SMs上。一个SM上可以同时运行多个块
在这个级别上通常不需要负载平衡。只需确保有足够的线程块可用于多次填充所有SMs。当一些SMs处于空闲状态且没有更多的线程块准备执行时,过度提供线程块以最小化内核末尾的负载不平衡是很有用的。其他人为理论问题提供了很好的答案
对于您的示例,您可以考虑将问题重组如下:
x
的N
点:[1,2,3,…,N]
x
的每个元素上计算一些复杂的函数,得到y
y
的子集,通过y10
生成y0
I have a vector x0 of N points: [1, 2, 3, ..., N]
I randomly pick 50% of the points and log them (or some complicated function) (1)
I write the resulting vector x1 to memory (2)
I repeat the above 2 operations on x1 to yield x2, and then do a further 8 iterations to yield x3 ... x10 (3)
I return x10 (4)