我编写的代码可以在GPU或CPU上运行。在CUDA存在包装器的情况下尝试在GPU上运行功能。如果出现错误(例如没有内存),它会尝试在CPU上运行它。如果再次出错,则返回0,否则返回1。 在CUDA缺失包装器的情况下,只尝试在CPU上运行函数。
这是我的宏:
#ifdef CUDA_FOUND
#define SET_F(FNARGS, FNSTRIP) int FNARGS{ \
if(!Only_CPU) if(CU ## FNSTRIP) return 1;\
if(CPU ## FNSTRIP) return 1; \
return 0; \
}
#else
#define SET_F(FNARGS, FNSTRIP) int FNARGS{ \
if(CPU ## FNSTRIP) return 1; \
return 0; \
}
#endif // CUDA_FOUND
要定义新功能,我将其称为:
SET_F(fillrandarr(size_t sz, char *arr), fillrandarr(sz, arr))
问题:有没有办法简化FNARGS
的宏分割参数以组成FNSTRIP
?即缩短上面的定义
SET_F(fillrandarr(size_t sz, char *arr))
答案 0 :(得分:4)
早上好在他的评论中写道:
Boost预处理器库可能可以做到这一点 Boost通常是C ++,但预处理器库只是一组宏,没有(据我所知)C ++特定的部分。
所以这是一个提升解决方案:
#define BOOST_PP_VARIADICS 1
#include <boost/preprocessor.hpp>
#define FOO(...) FOO2(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
#define FOO2(seq) FOO3(BOOST_PP_SEQ_HEAD(seq),BOOST_PP_SEQ_TAIL(seq))
#define FOO3(name, args) FOO6(name, \
BOOST_PP_SEQ_FOR_EACH_I(FOO4,,args), \
BOOST_PP_SEQ_FOR_EACH_I(FOO5,,args))
#define FOO4(rep, data, index, type) (type BOOST_PP_CAT(arg,index))
#define FOO5(rep, data, index, type) (BOOST_PP_CAT(arg,index))
#define FOO6(name, dargs, cargs) \
FOO8(name, FOO7(dargs, void), FOO7(cargs, ))
#define FOO7(seq, empty) \
BOOST_PP_IF(BOOST_PP_SEQ_SIZE(seq), \
BOOST_PP_SEQ_TO_TUPLE(seq), (empty))
#define FOO8(name, dargs, cargs) \
int name dargs { \
if (BOOST_PP_CAT(CPU_, name)cargs) \
return 1; \
return 0; \
}
FOO(fillrandarr, size_t, char*)
FOO(fun1, int, double)
FOO(fun2)
它生成这样的代码(由我添加的格式):
int fillrandarr (size_t arg0, char* arg1) {
if (CPU_fillrandarr(arg0, arg1))
return 1;
return 0;
}
int fun1 (int arg0, double arg1) {
if (CPU_fun1(arg0, arg1))
return 1;
return 0;
}
int fun2 (void) {
if (CPU_fun2())
return 1;
return 0;
}
我从宏调用中省略了参数的名称,因为它们实际上没有任何意义。已经采取特别的措施来处理最后一个案例,一个没有参数的函数,正确地在同一个框架中。
以下是不同的步骤:
()
但是对于函数定义,我们必须改为编写(void)
。答案 1 :(得分:1)
您无法使用预处理器拆分预处理符号,只能将它们组合在一起。这意味着“fillrandarr(sz,arr)”是预处理器的一个原子单元,因此不适合您的需求。您必须传递参数列表中分隔的符号,例如
#define SET_F(f_name,p1_type,p1_name,p2_type,p2_name) ...
对于进入函数的可变参数量,请使用
#define CNT_ARGS(...) CNT_ARGS_(__VA_ARGS__,8,7,6,5,4,3,2,1)
#define CNT_ARGS_(_1,_2,_3,_4,_5,_6,_7,_8,n) n
#define DROP_TYPE(...) DROP_TYPE_(CNT_ARGS(__VA_ARGS__),__VA_ARGS__)
#define DROP_TYPE_(n,...) DROP_TYPE__(n,__VA_ARGS__)
#define DROP_TYPE__(n,...) DROP_TYPE_##n(__VA_ARGS__)
#define DROP_TYPE_2(ptype,pname,...) pname
#define DROP_TYPE_4(ptype,pname,...) pname, DROP_TYPE_2(__VA_ARGS__)
#define DROP_TYPE_6(ptype,pname,...) pname, DROP_TYPE_4(__VA_ARGS__)
#define DROP_TYPE_8(ptype,pname,...) pname, DROP_TYPE_6(__VA_ARGS__)
#define FOO(fname,...) fname(DROP_TYPE(__VA_ARGS__))
FOO(my_func,t1,p1,t2,p2,t3,p3,t4,p4) -> my_func(p1,p2,p3,p4)
FOO(other_func,t1,p1,t2,p2) -> other_func(p1,p2)
答案 2 :(得分:1)
你可以使用不同数量的参数声明你已经拥有的函数的包装器宏:
#define SET_F_2(fname, \
vtype1, vname1, \
vtype2, vname2 \
) \
SET_F( \
fname( \
vtype1 vname1, \
vtype2 vname2 \
), \
fname( \
vname1, \
vname2 \
) \
)
#define SET_F_3(fname, \
vtype1, vname1, \
vtype2, vname2, \
vtype3, vname3 \
) \
SET_F( \
fname( \
vtype1 vname1, \
vtype2 vname2, \
vtype3 vname3 \
), \
fname( \
vname1, \
vname2, \
vname3 \
) \
)
... and so on
像这样使用:
SET_F_2(x, short, s, int, i);
SET_F_3(y, int, i, short, s, float, f);
使用 slartibartfast 提议来计算#define
的参数数量,这种方法肯定会针对更少的冗余进行优化。
答案 3 :(得分:1)
毕竟我做了下一件事(最多10个参数):
#define Fn1(A,B) A(x1)
#define Df1(A,B) A(B x1)
#define Fn2(A,B,C) A(x1, x2)
#define Df2(A,B,C) A(B x1, C x2)
#define Fn3(A,B,C,D) A(x1, x2, x3)
#define Df3(A,B,C,D) A(B x1, C x2, D x3)
#define Fn4(A,B,C,D,E) A(x1, x2, x3, x4)
#define Df4(A,B,C,D,E) A(B x1, C x2, D x3, E x4)
#define Fn5(A,B,C,D,E,F) A(x1, x2, x3, x4, x5)
#define Df5(A,B,C,D,E,F) A(B x1, C x2, D x3, E x4, F x5)
#define Fn6(A,B,C,D,E,F,G) A(x1, x2, x3, x4, x5, x6)
#define Df6(A,B,C,D,E,F,G) A(B x1, C x2, D x3, E x4, F x5, G x6)
#define Fn7(A,B,C,D,E,F,G,H) A(x1, x2, x3, x4, x5, x6, x7)
#define Df7(A,B,C,D,E,F,G,H) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7)
#define Fn8(A,B,C,D,E,F,G,H,I) A(x1, x2, x3, x4, x5, x6, x7, x8)
#define Df8(A,B,C,D,E,F,G,H,I) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8)
#define Fn9(A,B,C,D,E,F,G,H,I,J) A(x1, x2, x3, x4, x5, x6, x7, x8, x9)
#define Df9(A,B,C,D,E,F,G,H,I,J) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8, J x9)
#define Fn10(A,B,C,D,E,F,G,H,I,J,K) A(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)
#define Df10(A,B,C,D,E,F,G,H,I,J,K) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8, J x9, K x10)
#define DEF(N, ...) int Df ## N(__VA_ARGS__)
#define CONCAT(A, B) A ## B
#define FN(N, ...) Fn ## N(__VA_ARGS__)
#define DF(N, ...) Df ## N(__VA_ARGS__)
#define XFUNC(T, X) CONCAT(T, X)
#define FUNC(T, ...) XFUNC(T, FN(__VA_ARGS__))
#define DFUNC(T,...) EXTERN int XFUNC(T, DF(__VA_ARGS__))
#ifdef WRAPPER_C
// even when using cuda in case of fail CUDA init use CPU
static int Only_CPU =
#ifdef CUDA_FOUND
0
#else
1
#endif
;
#ifdef CUDA_FOUND
#define SET_F(...) DEF(__VA_ARGS__){ \
if(!Only_CPU) if(FUNC(CU, __VA_ARGS__)) return 1; \
if(FUNC(CPU, __VA_ARGS__)) return 1; \
return 0; \
}
#else
#define SET_F(...) DEF(__VA_ARGS__){ \
if(FUNC(CPU, __VA_ARGS__)) return 1; \
return 0; \
}
#endif // CUDA_FOUND
#else
#define SET_F(...)
#endif // WRAPPER_C
#ifdef CPU_C // file included from CPU.c
#define BOTH(...) DFUNC(CPU, __VA_ARGS__);
//#pragma message "CPUC"
#elif defined CUDA_CU //file included from CUDA.cu
#define BOTH(...) DFUNC(CU, __VA_ARGS__);
#elif defined WRAPPER_C // wrapper.c needs names of both wariants
#ifndef CUDA_FOUND
#define BOTH(...) DFUNC(CPU, __VA_ARGS__);
#else
#define BOTH(...) DFUNC(CU, __VA_ARGS__); DFUNC(CPU, __VA_ARGS__);
#endif // CUDA_FOUND
#else // file included from something else - just define a function
#define BOTH(...) DFUNC(, __VA_ARGS__);
#endif
#define DFN(...) BOTH(__VA_ARGS__) SET_F(__VA_ARGS__)
此代码位于文件wrapper.h中。 wrapper.c只包含代码的公共部分。
定义我在wrapper.h中编写的函数:
DFN(2, fillrandarr, size_t, float *)
DFN(6, bicubic_interp, float *, float *, size_t, size_t, size_t, size_t)