请考虑以下代码,将双浮点数的指数计算为常量表达式(采用IEEE 754标准指定的格式)。
template <typename T> constexpr T abs_CE(const T x){return x>=0?x:-x;}
constexpr unsigned long long int __double_exponent_CE_(const double x){return x==0?0:(x>=2.?(__double_exponent_CE_(x/2.)+1):(x<1?__double_exponent_CE_(x*2.)-1:0));}
constexpr unsigned long long int __double_exponent_CE(const double x){return (x==0)?0:(__double_exponent_CE_(abs_CE(x))+1023);}
对于某些输入(如std :: numeric_limits <double> :: max),该代码无法在正常编译标志的情况下在gcc中编译为常量表达式。它编译失败的原因是它超过了常量表达式的最大递归深度(512是默认值)。例如,std :: numeric_limits <double> :: max需要1024次调用,超出限制。
如果添加了标志-fconstexpr-depth = 2048,那么代码将完美编译,并计算为可以作为模板参数传递的常量表达式。
该代码无法在nvcc下使用标志-Xcompiler -fconstexpr-depth=2048
进行编译(特别是当nvcc发出cicc命令时崩溃),所以有没有办法改变nvcc中的深度限制?我没有在NVCC options找到任何改变它的旗帜。
为了防止在nvcc中没有这样的等效标志,是否有人知道在编译时使用少于512次递归调用计算double的指数的任何其他方法?
你应该考虑使用“--expt-relaxed-constexpr”标志:
实验标志:
允许主机代码调用
__device__constexpr
函数,并允许设备代码调用__host__constexpr
函数。请注意,此标志的行为可能会在将来的编译器版本中更改。
默认情况下,无法从具有不兼容执行空间的函数调用constexpr函数。实验性的nvcc标志
--expt-relaxed-constexpr
消除了这种限制。指定此标志后,主机代码可以调用__device__ constexpr
函数,设备代码可以调用__host__ constexpr
函数。