Неправильное количество аргументов в макросе препроцессора при передаче вызова ядра CUDA в качестве макроса аргумента - PullRequest
0 голосов
/ 17 января 2020

У меня есть следующий макрос

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

, который я использую для очень простых временных отрезков кода. Однако вызовы макросов чувствительны к запятым, а вызов ядра CUDA (с использованием синтаксиса тройного шеврона) заставляет препроцессор полагать, что макросу передается более 2 аргументов.

Есть ли способ обойти это?

1 Ответ

1 голос
/ 17 января 2020

Начиная с C99 / C ++ 11, вы можете использовать макрос аргумента c variadi (varargs) для решения этой проблемы. Вы пишете макрос varargs, используя ... в качестве последнего параметра; в теле макроса __VA_ARGS__ будет заменено завершающими аргументами из вызова макроса с неповрежденными запятыми:

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

Для компиляторов без поддержки макроса varargs ваша единственная альтернатива - попытаться защитить все запятые, используя их только в скобках c выражений. Поскольку круглые скобки защищают запятые от использования в качестве разделителей аргументов макроса, многие запятые, естественно, безопасны. Но есть много исключений, таких как списки аргументов шаблона C ++ (<> не защищает запятые), объявления нескольких объектов и, как вы говорите, тройные вызовы шеврона. Некоторые из них может быть труднее защитить, чем другие.

В частности, я не знаю, можно ли, например, поставить избыточные скобки вокруг вызова ядра CUDA. Конечно, если nvcc обрабатывает макросы varargs, вам это не нужно. Но на основании этого сообщения об ошибке я не уверен. nvcc основан на компиляции EDG, которая соответствует требованиям, но nvidia, похоже, не пришла в голову документировать, какая версия стандарта используется.

...