Cuda 我可以在编译时确定是否设置了--use\u fast\u math吗?

Cuda 我可以在编译时确定是否设置了--use\u fast\u math吗?,cuda,nvcc,fast-math,Cuda,Nvcc,Fast Math,我正在编写一些CUDA代码,我希望它根据是否设置了--use\u fast\u math而有不同的行为。我想在编译时做出决定,而不是在运行时 当设置了--use\u fast\u math时,NVCC似乎不会添加或更改预处理器定义。我通过比较以下各项的输出来检查这一点: nvcc -Xcompiler -dM -E -x cu - 输出 nvcc -Xcompiler -dM -E --use_fast_math -x cu - 他们完全一样;所以那条路好像被堵住了。现在,如果编译用户调用N

我正在编写一些CUDA代码,我希望它根据是否设置了
--use\u fast\u math
而有不同的行为。我想在编译时做出决定,而不是在运行时

当设置了
--use\u fast\u math
时,NVCC似乎不会添加或更改预处理器定义。我通过比较以下各项的输出来检查这一点:

nvcc -Xcompiler -dM -E -x cu -
输出

nvcc -Xcompiler -dM -E --use_fast_math -x cu -
他们完全一样;所以那条路好像被堵住了。现在,如果编译用户调用NVCC时使用
——使用\u fast\u math-DUSING\u fast\u math
,那么我也可以检测到;但是假设它是库代码,我们不能对用户施加这些限制

对于正在编译的代码,是否有其他方法可以注意到
--use\u fast\u math
处于启用状态


注:“注意”可能意味着使用预处理器
#if
#ifdef
指令,使用SFINAE,使用编译器内置值或constexpr函数-编译时可用的任何函数。

答案几乎肯定是否定的。快速数学函数是硬件指令,它们由CUDA设备代码编译器内的代码生成代替。例如:

$ cat nonsense.cu

__global__ void kernel(float* in, float* out)
{
    int idx = threadIdx.x + blockIdx.x * blockDim.x;

    out[idx] = sqrtf(cosf(in[idx]));
}

$ nvcc -v -arch=sm_60 --keep -c --use_fast_math nonsense.cu 
#$ _SPACE_= 
#$ _CUDART_=cudart
#$ _HERE_=/opt/cuda-10.1/bin
#$ _THERE_=/opt/cuda-10.1/bin
#$ _TARGET_SIZE_=
#$ _TARGET_DIR_=
#$ _TARGET_DIR_=targets/x86_64-linux
#$ TOP=/opt/cuda-10.1/bin/..
#$ NVVMIR_LIBRARY_DIR=/opt/cuda-10.1/bin/../nvvm/libdevice
#$ LD_LIBRARY_PATH=/opt/cuda-10.1/bin/../lib:/opt/cuda-10.1/lib64
#$ PATH=/opt/cuda-10.1/bin/../nvvm/bin:/opt/cuda-10.1/bin:/opt/miniconda3/bin:/opt/miniconda3/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/cuda-10.1/bin
#$ INCLUDES="-I/opt/cuda-10.1/bin/../targets/x86_64-linux/include"  
#$ LIBRARIES=  "-L/opt/cuda-10.1/bin/../targets/x86_64-linux/lib/stubs" "-L/opt/cuda-10.1/bin/../targets/x86_64-linux/lib"
#$ CUDAFE_FLAGS=
#$ PTXAS_FLAGS=
#$ gcc -std=c++14 -D__CUDA_ARCH__=600 -E -x c++  -DCUDA_DOUBLE_MATH_FUNCTIONS -D__CUDACC__ -D__NVCC__  "-I/opt/cuda-10.1/bin/../targets/x86_64-linux/include"    -D__CUDACC_VER_MAJOR__=10 -D__CUDACC_VER_MINOR__=1 -D__CUDACC_VER_BUILD__=105 -include "cuda_runtime.h" -m64 "nonsense.cu" > "nonsense.cpp1.ii" 
#$ cicc --c++14 --gnu_version=70400 --allow_managed   -arch compute_60 -m64 -ftz=1 -prec_div=0 -prec_sqrt=0 -fmad=1 -fast-math --gen_div_approx_ftz --include_file_name "nonsense.fatbin.c" -tused -nvvmir-library "/opt/cuda-10.1/bin/../nvvm/libdevice/libdevice.10.bc" --gen_module_id_file --module_id_file_name "nonsense.module_id" --orig_src_file_name "nonsense.cu" --gen_c_file_name "nonsense.cudafe1.c" --stub_file_name "nonsense.cudafe1.stub.c" --gen_device_file_name "nonsense.cudafe1.gpu"  "nonsense.cpp1.ii" -o "nonsense.ptx"
#$ ptxas -arch=sm_60 -m64  "nonsense.ptx"  -o "nonsense.sm_60.cubin" 
#$ fatbinary --create="nonsense.fatbin" -64 "--image=profile=sm_60,file=nonsense.sm_60.cubin" "--image=profile=compute_60,file=nonsense.ptx" --embedded-fatbin="nonsense.fatbin.c" 
#$ gcc -std=c++14 -E -x c++ -D__CUDACC__ -D__NVCC__  "-I/opt/cuda-10.1/bin/../targets/x86_64-linux/include"    -D__CUDACC_VER_MAJOR__=10 -D__CUDACC_VER_MINOR__=1 -D__CUDACC_VER_BUILD__=105 -include "cuda_runtime.h" -m64 "nonsense.cu" > "nonsense.cpp4.ii" 
#$ cudafe++ --c++14 --gnu_version=70400 --allow_managed  --m64 --parse_templates --gen_c_file_name "nonsense.cudafe1.cpp" --stub_file_name "nonsense.cudafe1.stub.c" --module_id_file_name "nonsense.module_id" "nonsense.cpp4.ii" 
#$ gcc -std=c++14 -D__CUDA_ARCH__=600 -c -x c++  -DCUDA_DOUBLE_MATH_FUNCTIONS "-I/opt/cuda-10.1/bin/../targets/x86_64-linux/include"   -m64 -o "nonsense.o" "nonsense.cudafe1.cpp" 

$ cat nonsense.ptx
//
// Generated by NVIDIA NVVM Compiler
//
// Compiler Build ID: CL-25769353
// Cuda compilation tools, release 10.1, V10.1.105
// Based on LLVM 3.4svn
//

.version 6.4
.target sm_60
.address_size 64

    // .globl   _Z6kernelPfS_

.visible .entry _Z6kernelPfS_(
    .param .u64 _Z6kernelPfS__param_0,
    .param .u64 _Z6kernelPfS__param_1
)
{
    .reg .f32   %f<4>;
    .reg .b32   %r<5>;
    .reg .b64   %rd<8>;


    ld.param.u64    %rd1, [_Z6kernelPfS__param_0];
    ld.param.u64    %rd2, [_Z6kernelPfS__param_1];
    cvta.to.global.u64  %rd3, %rd2;
    cvta.to.global.u64  %rd4, %rd1;
    mov.u32     %r1, %tid.x;
    mov.u32     %r2, %ctaid.x;
    mov.u32     %r3, %ntid.x;
    mad.lo.s32  %r4, %r3, %r2, %r1;
    mul.wide.s32    %rd5, %r4, 4;
    add.s64     %rd6, %rd4, %rd5;
    ld.global.f32   %f1, [%rd6];
    cos.approx.ftz.f32  %f2, %f1;
    sqrt.approx.ftz.f32     %f3, %f2;
    add.s64     %rd7, %rd3, %rd5;
    st.global.f32   [%rd7], %f3;
    ret;
}
$cat.cu
__全局无效内核(浮点*入,浮点*出)
{
int idx=threadIdx.x+blockIdx.x*blockDim.x;
out[idx]=sqrtf(cosf(in[idx]);
}
$nvcc-v-arch=sm\u 60--keep-c--use\u fast\u math.cu
#$\u空间=
#$\u CUDART\uu=CUDART
#$\u此处\=/opt/cuda-10.1/bin
#$\u THERE.=/opt/cuda-10.1/bin
#$\目标\大小_=
#$\u目标\u目录_=
#$\u TARGET\u DIR=targets/x86\u 64-linux
#$TOP=/opt/cuda-10.1/bin/。。
#$NVVMIR_LIBRARY_DIR=/opt/cuda-10.1/bin/。/nvvm/libdevice
#$LD_LIBRARY_PATH=/opt/cuda-10.1/bin/。/lib:/opt/cuda-10.1/lib64
#$PATH=/opt/cuda-10.1/bin//nvm/bin:/opt/cuda-10.1/bin:/opt/miniconda3/bin:/opt/miniconda3/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/games:/snap/bin:/opt/cuda-10.1/bin
#$INCLUDES=“-I/opt/cuda-10.1/bin/。/targets/x86_64-linux/include”
#$LIBRARIES=“-L/opt/cuda-10.1/bin/。/targets/x86_64-linux/lib/stubs”“-L/opt/cuda-10.1/bin/。/targets/x86_64-linux/lib”
#$CUDAFE_旗帜=
#$PTXAS_标志=
-xC++(dcUAdAddiLyMathyType)-Dy-CudAccCasy- DynNvccCy]“-I/OPT/CUAD-101/BIN…/Talks/x86Y64-Linux /包含”-Dy-CudAccVracVyMyRoMrOrg==10 - DuqCuccAcVrimyMiNrOrthy==1 DyCucAccVraceVuuBugdId==105 -包括“CUAAYRunTime.h”-M64“无稽之谈.Cu”>“无稽之谈.CPP1.II”γ$ GCC - STD=C++ 14 - Dy-CuaajCARCHYG==600 -E
#$cicc--c++14--gnu_版本=70400--allow_managed-arch compute_60-m64-ftz=1-prec_div=0-prec_sqrt=0-fmad=1-fast math--gen_div_近似_ftz--include_文件名“arouse.fatbin.c”-tused-nvvmir库/opt/cuda-10.1/bin/./nvvm/libdevice/libdevice/libdevice.10.bc”--gen模块id_文件名“arouse.module”--orig_src_file_name“russy.cu”--gen_c_file_name“russy.cudafe1.c”--stub_file_name“russy.cudafe1.c”--gen_设备_file_name“russy.cudafe1.gpu”“russy.cpp1.ii”--o“russy.ptx”
#$ptxas-arch=sm_60-m64“胡说.ptx”-o“胡说.sm_60.cubin”
#$fatbinary--create=“raush.fatbin”-64--image=profile=sm_60,file=raush.sm_60.cubin”--image=profile=compute_60,file=raush.ptx”--嵌入式fatbin=“raush.fatbin.c”
$ GCC - STD=C++ 14 -E-XC++-Dy-CUdACCKY- DY-NVCCZY“-I/OPT/CUAD-101/bin /…/Mask/X86Y64-Linux /包含”-DyCuCaskVielMyMrOrthyz=10 - Dy-CudAccVracVyMyRoRyC++=1 - DuyCucAccVraceBuffdIdg= 105=-包括“CUAULRunTime.h”-M64“无稽之谈.Cu”>“无稽之谈.CPP4.II”γ
#$cudafe++--c++14--gnu_version=70400--allow_managed--m64--parse_模板--gen_c_文件名“jussy.cudafe1.cpp”--存根文件名“jussy.cudafe1.stub.c”--模块id文件名“jussy.module_id”“jussy.cpp4.ii”
{ $ GCC - STD= C++ 14 - Dy-CuaajARCHARGY=600 -C-X+C++ -DCUAAUDULYLY MththIORE函数“-I/OPT/CUDA-101/bin/…/Mask/X86Y64-Linux /包含”-M64 -O”无意义。O“无稽之谈。CUADAFE1.CPP”
$cat.ptx
//
//由NVIDIA NVVM编译器生成
//
//编译器内部版本ID:CL-25769353
//Cuda编译工具,10.1版,V10.1.105
//基于LLVM3.4svn
//
.6.4版
.目标sm_60
.地址大小64
//.globl_Z6kernelPfS_
.visible.entryz6kernelpfs_(
.param.u64_Z6kernelPfS_uuparam_0,
.param.u64_Z6kernelPfS_uuparam_1
)
{
.reg.f32%f;
.注册号b32%r;
.reg.b64%rd;
ld.param.u64%rd1,[\u Z6kernelPfS\u\u param\u 0];
ld.param.u64%rd2,[\u Z6kernelPfS\u\u param\u 1];
cvta.to.global.u64%rd3,%rd2;
cvta.to.global.u64%rd4,%rd1;
mov.u32%r1,%tid.x;
mov.u32%r2,%ctaid.x;
mov.u32%r3,%ntid.x;
mad.lo.s32%r4、%r3、%r2、%r1;
mul.wide.s32%rd5,%r4,4;
add.s64%rd6、%rd4、%rd5;
ld.global.f32%f1,[%rd6];
cos.约为自由贸易区f32%f2,%f1;
面积约为平方英尺f32%f3%f2;
add.s64%rd7、%rd3、%rd5;
st.global.f32[%rd7],%f3;
ret;
}

您可以看到,没有nvcc引导的预处理器魔法,只有传递给设备编译器的参数,这些参数产生了带有必要指令的PTX代码。这意味着,从理论上讲,你可能会通过LLVM黑客来拦截或识别你正在寻找的字节码,但我非常怀疑这就是你的想法。

这里是一个丑陋的难题,而不是答案:

在代码中放置以下内容:

#ifndef I_ENABLED_FAST_MATH_REALLY_I_DID_PLEASE_BELIEVE_ME
#warning "Foo library is possibly being compiled without `--use_fast_math`. Please enable that switch, and define I_ENABLED_FAST_MATH_REALLY_I_DID_PLEASE_BELIEVE_ME, to avoid this message.
#endif

虽然这不会强迫你的用户去做你想做的事情,但至少会让他们这么做,这已经够烦人的了。(当然,他们可以简单地用预处理器定义禁用警告。)

当你说“正在编译的代码要注意”时,你真的是指预处理器吗?正在编译的代码如何“注意”任何东西?(我确信答案是否定的,这实际上是中金公司内部代码生成控制,IIRC)@Talonmes:请参见编辑。预处理器是我最初希望使用的,但是看起来