如何解决 CUDA 中对 threadIdx.x、blockDim.x 和 blockIdx.x 的未定义引用错误?

Posted

技术标签:

【中文标题】如何解决 CUDA 中对 threadIdx.x、blockDim.x 和 blockIdx.x 的未定义引用错误?【英文标题】:How to resolve undefined reference errors to threadIdx.x, blockDim.x, and blockIdx.x in CUDA? 【发布时间】:2022-01-24 02:11:28 【问题描述】:

我是一名在 CUDA 中研究并行列表排名算法的初学者。我不知道为什么在使用“nvcc ParallelListRanking.cu -o ParallelListRanking”进行编译时,会出现未定义的对 threadIdx.x、blockDim.x 和 blockIdx.x 的引用错误,并显示消息“ld 返回了退出 1 状态”。添加 #include "device_launch_parameters.h" 和 #include "cuda.h" 没有帮助。有什么想法可以解决这个问题?

#include<stdio.h>
#include <device_launch_parameters.h>
#include <cuda.h>

__global__ void set_up(unsigned long int n, unsigned long int *dS, unsigned long long int *dQR)

        unsigned long int i = threadIdx.x + blockDim.x * blockIdx.x;

        if (i < n) 
                dS[i] = i + 1;
                dS[n-1] = 0;

                if (dS[i] != 0) 
                        dQR[i] = (dQR[i]%(1ull<<32)) + (1ull<<32) * 1ull;
                
                else 
                        dQR[i] = (dQR[i]%(1ull<<32)) + (1ull<<32) * 0ull;
                

                dQR[i] = ((unsigned long long int) dS[i])%(1ull<<32) + (1ull<<32)*(dQR[i]/(1ull<<32));
        


__global__ void update(unsigned long int n, unsigned long long int *dQR) 

        unsigned long int i = threadIdx.x + blockDim.x * blockIdx.x;

        if (i < n) 
                unsigned long int tempdQ = (unsigned long int) (dQR[i]%(1ull<<32));
                unsigned long int tempdQQ = (unsigned long int) (dQR[tempdQ]%(1ull<<32));

                if (tempdQ != 0 && tempdQQ != 0) 
                        unsigned long long int tmpdQRQ = dQR[tempdQ];

                        unsigned long int tempdR = (unsigned long int) dQR[i]/(1ull<<32);
                        unsigned long long int tempdRQ = tmpdQRQ/(1ull<<32);

                        dQR[i] = ((unsigned long long int) tempdQQ)%(1ull<<32) + (((unsigned long long int) tempdR) + tempdRQ)*(1ull<<32);

                        tempdQ = tempdQQ;
                        tempdQQ = (unsigned long int) dQR[tempdQ]%(1ull<<32);
                
        


int main() 

        unsigned long int n = 1000;
        unsigned long int *dS =(unsigned long int *) cudaMalloc((int **)n, sizeof(unsigned long int));
        unsigned long long int *dQR = (unsigned long long int *) cudaMalloc((int **)n, sizeof(unsigned long long int));
        unsigned long int i = threadIdx.x + blockDim.x * blockIdx.x;

        set_up<<< 100, 100 >>>(n, dS, dQR);

        for (int t = 1; t < n; t++) 
                update<<< 100, 100>>>(n, dQR);
        

        printf("%lu", (unsigned long int) (dQR[i]%(1ull<<32)));
        printf("\n");
        printf("%lu", (unsigned long int) (dQR[i]/(1ull<<32)));

        cudaFree(dQR);
        cudaFree(dS);

        return 0;

【问题讨论】:

【参考方案1】:

你不能这样做:

unsigned long int i = threadIdx.x + blockDim.x * blockIdx.x;

在主机代码中(即main())。

这些变量仅在设备代码中自动定义(例如,用__global__ 修饰的例程)。

从那时起,您的主机代码的其余部分不应依赖于像 threadIdx.x 这样的变量,因为它们没有在主机代码中定义并且在那里使用没有意义。

因此,只需完全删除该行(来自main()),然后想出另一种方法来在您的主机代码中使用类似的索引。

您似乎使用它的唯一地方是在您的 printf 语句中,所以我猜如果您尝试打印出所有变量,您将需要在主机代码中进行循环:

for (int i = 0; i < n; i++)
    printf("%lu", (unsigned long int) (dQR[i]%(1ull<<32)));
    printf("\n");
    printf("%lu", (unsigned long int) (dQR[i]/(1ull<<32)));

这是您报告的错误的近因,但是您的代码还有其他问题。

cudaMalloc 的用法不正确:

    unsigned long int *dS =(unsigned long int *) cudaMalloc((int **)n, sizeof(unsigned long int));

你想做这样的事情:

    cudaMallocManaged(&dS, sizeof(unsigned long int)*n);

同样适用于dQR。 (我在这里从cudaMalloc 切换到cudaMallocManaged 的原因与您尝试从主机代码打印这些变量有关。)

您的代码可能还有其他问题。在尝试这样的事情之前,我建议您牢牢掌握如何在 CUDA 中编写一个适当、简单的矢量添加应用程序。

要基本掌握 CUDA,您可能需要学习一个简单的示例代码,例如 vectorAdd,也可能需要学习 the introductory blogs 中的一个。

【讨论】:

以上是关于如何解决 CUDA 中对 threadIdx.x、blockDim.x 和 blockIdx.x 的未定义引用错误?的主要内容,如果未能解决你的问题,请参考以下文章

cuda 编 程 helloworld 打印 blockIdx和threadIdx.x threadIdx.y

CUDA中的2D线程

cuda 编程 helloworld 打印 blockIdx和threadIdx

CUDA 中的分歧 - 从内核中的线程退出

怎么可以设计更多的线程cuda

CUDA在内核代码中多次乘法运算