将 CUDA 内核调用作为参数宏传递时,预处理器宏中的参数数量不正确

Incorrect number of arguments in preprocessor macro when passing CUDA kernel call as argument macro

我有以下宏

#define TIMEIT( variable, body ) \
variable = omp_get_wtime(); \
body; \
variable = omp_get_wtime() - variable;

我用它来非常简单地为代码段计时。 但是,宏调用对逗号敏感,并且 CUDA 内核调用(使用三人字形语法)导致预处理器认为宏正在传递超过 2 个参数。

有办法解决这个问题吗?

从C99/C++11开始,您可以使用可变参数(varargs)宏来解决这个问题。您使用 ... 作为最后一个参数编写可变参数宏;在宏的主体中,__VA_ARGS__ 将替换为宏调用的尾随参数,逗号完整:

#define TIMEIT( variable, ... )   \
    variable = omp_get_wtime();   \
    __VA_ARGS__;                  \
    variable = omp_get_wtime() - variable;

对于不支持可变参数宏的编译器,您唯一的选择是尝试通过仅在括号表达式中使用逗号来保护所有逗号。因为括号保护逗号不被视为宏参数定界符,所以许多逗号自然是安全的。但也有很多例外,例如 C++ 模板参数列表(<> 不保护逗号)、多个对象的声明,以及——正如你所说的——三重雪佛龙调用。其中一些可能比其他的更难保护。

特别是,我不知道您是否可以在 CUDA 内核调用周围放置多余的括号。当然,如果 nvcc 确实处理可变参数宏,则您不需要这样做。但是基于这个 bug report,我不太确定。 nvcc 基于符合标准的 EDG 编译器,但 nvidia 似乎没有记录正在使用哪个版本的标准。