Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
挂接CUDA驱动程序API调用_Api_Cuda_Hook_Shared Objects_Ld Preload - Fatal编程技术网

挂接CUDA驱动程序API调用

挂接CUDA驱动程序API调用,api,cuda,hook,shared-objects,ld-preload,Api,Cuda,Hook,Shared Objects,Ld Preload,我试图使用LD_预加载技巧,以窃取CUDA驱动程序API调用cu*函数。我首先为内核实现了一个简单的存根函数,如下所示: #define _GNU_SOURCE #include <cuda.h> #include <dlfcn.h> #include <stdio.h> //#include <cuda_runtime.h> //#include <driver_types.h> void cuLaunchKernelHelper

我试图使用LD_预加载技巧,以窃取CUDA驱动程序API调用cu*函数。我首先为内核实现了一个简单的存根函数,如下所示:

#define _GNU_SOURCE
#include <cuda.h>
#include <dlfcn.h>
#include <stdio.h>
//#include <cuda_runtime.h>
//#include <driver_types.h>

void cuLaunchKernelHelper (CUstream hStream);


CUresult cuLaunchKernel (CUfunction f, unsigned int gridDimX, unsigned int gridDimY, unsigned int gridDimZ, unsigned int blockDimX, unsigned int blockDimY, unsigned int blockDimZ, unsigned int sharedMemBytes, CUstream hStream, void** kernelParams, void** extra) {

        void* handle;
        CUresult (*function)(CUfunction f,  
                        unsigned int gridDimX, unsigned int gridDimY, unsigned int gridDimZ, 
                        unsigned int blockDimX, unsigned int blockDimY, unsigned int blockDimZ,
                        unsigned int sharedMemBytes, CUstream hStream, void** kernelParams, void** extra);

        *(void **)(&function) = dlsym (RTLD_NEXT, "cuLaunchKernel");

        cuLaunchKernelHelper (hStream);

        (*function)(f, gridDimX, gridDimY, gridDimZ, blockDimX, blockDimY, blockDimZ, sharedMemBytes, hStream, kernelParams, extra);

}

void cuLaunchKernelHelper (CUstream hStream) {
        // Nothing
        printf ("cuLaunchHelper\n");
}
LD_PRELOAD="stub.so" ./matrixMul
不幸的是,什么也没有发生。我无法捕捉这个CUDA呼叫。现在我想知道,关于CUDA二进制代码,我需要考虑什么特别的事情?

现在我想知道,关于CUDA二进制代码有什么特别的问题需要考虑吗?

对。您需要确保正在应用LD_预加载技巧的代码实际调用了内核,并且与CUDA驱动程序API库进行了动态链接。您会发现,使用nvcc编译的运行时API应用程序(这是您将遇到的大部分CUDA代码)使用编译器生成的样板文件,该样板文件解析为已弃用的culunch API,而不是culunch内核。这就是为什么您什么也看不到,因为您的代码截取了一个API,该API没有在您正在测试的应用程序中调用,也没有动态链接到驱动程序库


正如评论中所指出的,如果您像所列的任何示例一样使用驱动程序API应用程序,那么它应该可以按预期工作。

当我在实际调用内核的驱动程序API应用程序(如vectorAddDrvI)上运行它时,您的方法对我来说非常有效。CUDA库本身使用dlsym获取调用函数。与拦截错误的函数无关。虽然具体的基本行为随着时间的推移发生了变化,但这两个观察结果在这里都是正确的,因此可能因CUDA版本而异。在CUDA 9.1上,libcuda.so由libcudart在运行时加载,dlsym连接到一大组函数,例如ltrace./myexe 2>&1 | grep cu。因此,无法通过普通LD_预加载截取访问特定函数调用。然而,这个答案中的陈述也是正确的,也就是说:您需要确保应用LD_预加载技巧的代码实际调用了内核。您编写的代码必须调用此函数,此函数才能工作。LD_PRELOAD方法允许您拦截对动态链接库的调用。libcuda.so不是动态链接的,而是使用lddt验证典型的CUDA运行时API应用程序,在使用时,它是运行时加载的。它通常动态链接到CUDA驱动程序API应用程序,而内核是CUDA驱动程序API的一部分。如果您构建的cuda运行时应用程序动态链接到libcudart,而libcudart不是默认的编译选项,那么您应该能够拦截来自运行时API的启动调用,例如cudaLaunch。