第一个问题:
假设我需要在计算能力为 1.3 的 Tesla C1060 上启动具有 229080 个线程的内核。
所以根据文档,这台机器有 240 个内核,每个对称多处理器上有 8 个内核,总共有 30 个 SM。
对于“并发”运行的总共 30720 个线程,每个 SM 最多可以使用 1024 个线程。
现在,如果我定义 256 个线程的块,这意味着每个 SM 可以有 4 个块,因为 1024/256=4。因此,这 30720 个线程可以跨所有 SM 排列在 120 个块中。
现在对于我的 229080 线程示例,我需要 229080/256=~895(向上取整)块来处理所有线程。
现在假设我想调用一个内核,我必须使用那些 229080 线程,所以我有两个选择。第一个是我划分问题,以便我在 for 循环中调用内核约 8 次,每次使用 120 个块和 30720 个线程的网格(229080/30720)。这样我可以确保设备将完全被占用。另一种选择是为整个 229080 个线程使用 895 个块的网格调用内核,在这种情况下,许多块将保持空闲状态,直到 SM 完成它拥有的 8 个块。
那么哪个是首选呢?这些块保持空闲等待有什么不同吗?他们占用资源吗?
第二个问题
假设在我调用的内核中,我需要访问未合并的全局内存,因此可以选择使用共享内存。
然后,我可以使用每个线程从全局内存上的数组中提取一个值,比如global_array
长度为 229080。现在我理解正确,您必须在复制到共享内存时避免分支,因为块上的所有线程都需要syncthreads()
调用确保他们都可以访问共享内存。
这里的问题是,对于 229080 个线程,我正好需要 229080/256=894.84375 个块,因为有 216 个线程的剩余部分。我可以将这个数字四舍五入得到 895 个块,最后一个块将只使用 216 个线程。
但是由于我需要将值提取到global_array
长度为 229080 的共享内存中,并且我不能使用条件语句来防止最后 40 个线程(256-216)访问非法地址,global_array
那么我该如何规避这个问题而使用共享内存加载?