所以我现在还不明白:为什么这个'复杂'的架构不仅仅像在CPU上说的那样:'好吧,GPU有N核,就是这样!'?
假设我有一个特定的程序被分成B块的网格和每个T线程的块(总共B * T个线程),我可以告诉你一个块总是连接到ONE SM还是NOT?因为如果它是这样的话,这将使编码器变得更难,因为他应该知道有多少SM来优化每个图形卡的并行化。例如:当我有一个带有8个SM的图形卡时,我的程序只会将数据分成带有N个线程的1个块的网格,我只能使用一个不会使用其所有资源的SM!
在编写程序时,有没有办法只使用卡的某些线程?我真的很想通过在1..M线程上运行我的程序来对加速进行基准测试,其中M是cuda核心的总数(如果这相当于'thread'),但是如何做到这一点?这样编写我的程序就足够了:
cudaKernel<<<1, 1>>>(...)
到
cudaKernel<<<1, M>>>(...)
每次运行它?我在这里看到的唯一问题是:让我们假设我有简单的向量加法示例:
#define SIZE 10
__global__ void vecAdd(float* A, float* B, float* C)
{
int i = threadIdx.x;
A[i]=0;
B[i]=i;
C[i] = A[i] + B[i];
}
int main()
{
int N=SIZE;
float A[SIZE], B[SIZE], C[SIZE];
// Kernel invocation
float *devPtrA;
float *devPtrB;
float *devPtrC;
[...]
vecAdd<<<1, N>>>(devPtrA, devPtrB, devPtrC);
}
当我现在将vecAdd<<<1, N>>>
设置为vecAdd<<<1, 1>>>
时,单个线程不会将C计算为N大小的向量,因为唯一的线程只计算A,B的第一个值,因此C如何克服这个问题呢?
非常感谢您提前澄清!!你会帮助我很多!
答案 0 :(得分:2)
在大多数情况下,你所询问的大多数问题的答案都是否定的。不只是,但是没有。
大多数GPU编程的一般想法是它应该是隐式可伸缩的 - 即,您的代码会自动使用尽可能多的内核。特别是,当它用于图形处理时,核心在执行三种类型的着色器(顶点,几何,片段/像素)之间分离。因此,可用核心的数量可以(并且通常会)动态变化,具体取决于总体负载。
以这种方式组织GPU有几个原因,而不是像典型的多核CPU那样。首先,它主要用于“令人尴尬的并行”问题 - 显然,其主要目的是将相似的代码应用于大量像素中的每一个。虽然在使用CUDA代码时你并没有完全相同,但这仍然是硬件设计的基础。其次,如上所述,核心实际上在至少三个不同目的之间分开,并且可以在更多核心之间分开(例如,使用某些核心的图形应用程序,以及使用其他核心的CUDA代码)。第三,额外的抽象有助于保持代码免受硬件变化的影响。它允许您仅指定所需的计算,并且它可以尽可能高效地在硬件上进行调度。