我是 CUDA 初学者。
到目前为止,我了解到,每个 SM 有 8 个块(线程)。假设我将数组中的元素乘以 2 的简单工作。但是,我的数据比线程少。
没问题,因为我可以切断线程的“尾巴”以使它们空闲。但是,如果我理解正确,这将意味着一些 SM 将获得 100% 的工作,而一部分(甚至没有)。
因此,我想计算哪个 SM 正在运行给定线程并以这样的方式进行计算,即每个 SM 具有相同的工作量。
我希望它首先有意义:-)如果是这样,如何计算给定线程正在运行哪个SM?或者——当前SM的索引和它们的总数?换句话说,在 SM 术语中相当于 threadDim/threadIdx。
更新
评论太长了。
罗伯特,谢谢你的回答。当我尝试消化所有内容时,这就是我所做的——我有一个“大”数组,我只需将值相乘*2
并将其存储到输出数组(作为热身;顺便说一句。我所做的所有计算,在数学上都是正确的)。所以首先我在 1 个块,1 个线程中运行它。美好的。接下来,我尝试以这样一种方式拆分工作,即每个乘法只由一个线程完成一次。结果我的程序运行速度慢了大约 6 倍. 我什至感觉到为什么——获取有关 GPU 的信息的小惩罚,然后计算我应该使用多少块和线程,然后在每个线程中而不是单次乘法,现在我有大约 10 个额外的乘法来计算数组中的偏移量一个线程。一方面我试图找出如何改变这种不受欢迎的行为,另一方面我想在 SM 之间平均分布线程的“尾巴”。
我改写 - 也许我错了,但我想解决这个问题。我有 1G*2
的小作业(仅此而已)——我应该用 1K 线程创建 1K 块,还是用 1 个线程创建 1M 块,用 1M 线程创建 1 个块,等等。到目前为止,我阅读了 GPU 属性,划分、划分和盲目地使用网格/块的每个维度的最大值(或所需的值,如果没有要计算的数据)。
编码
size
是输入和输出数组的大小。一般来说:
output_array[i] = input_array[i]*2;
计算我需要多少块/线程。
size_t total_threads = props.maxThreadsPerMultiProcessor
* props.multiProcessorCount;
if (size<total_threads)
total_threads = size;
size_t total_blocks = 1+(total_threads-1)/props.maxThreadsPerBlock;
size_t threads_per_block = 1+(total_threads-1)/total_blocks;
Haveprops.maxGridSize
和props.maxThreadsDim
I 以类似的方式计算块和线程的尺寸 - 从total_blocks
和threads_per_block
.
然后是杀手部分,计算线程的偏移量(“内部”线程):
size_t offset = threadIdx.z;
size_t dim = blockDim.x;
offset += threadIdx.y*dim;
dim *= blockDim.y;
offset += threadIdx.z*dim;
dim *= blockDim.z;
offset += blockIdx.x*dim;
dim *= gridDim.x;
offset += blockIdx.y*dim;
dim *= gridDim.y;
size_t chunk = 1+(size-1)/dim;
所以现在我有了当前线程的起始偏移量,以及用于乘法的数组(块)中的数据量。我没有在grimDim.z
上面使用,因为 AFAIK 总是 1,对吧?