编译GPU的C ++程序的一部分

时间:2014-05-22 13:14:31

标签: c++ dynamic-linking nvcc

是否可以将带有nvcc的GPU编译(C ++)代码转换为共享对象(.so文件)并从C ++程序动态加载它(在本例中为Cern' ROOT,这基本上是C++ interpreter(" CINT"))。

我想要运行的一个简单示例是:

extern "C"
void TestCompiled() {
  printf("test\n");
  exit(0); 
}

此代码是使用nvcc --compiler-options '-fPIC' -o TestCompiled_C.so --shared TestCompiled.cu编译的。使用以下命令将共享对象加载到ROOT中:

{ // Test.C program
  int error, check;
  check = gROOT->LoadMacro("TestCompiled_C.so", &error);
  cout << "check " << check << " " << " error: " << error << endl;
  TestCompiled();  // run macro
  exit(0); 
}

加载库OK,但找不到TestCompiled()

$ root -b -l Test.C
root [0] 
Processing Test.C...
check 0  error: 0
Error: Function Hello() is not defined in current scope  Test.C:11:
*** Interpreter error recovered ***

通过使用ROOT编译第一个测试脚本(没有extern行,使用root TestCompiled.C++编译)来做同样的工作......我可以尝试什么才能使C ++程序找到测试函数nvcc编译吗?

2 个答案:

答案 0 :(得分:1)

我假设输出的共享对象文件与任何其他共享库一样,例如使用共享选项使用GCC创建的共享库。在这种情况下,要动态加载对象,您需要使用dlopen函数来获取共享对象的句柄。然后,您可以使用dlsym函数在文件中查找符号。

void *object_handle = dlopen("TestCompiled_C.so", RTLD_NOW);
if (object_handle == NULL)
{
  printf("%s\n", dlerror());
  // Exit or return error code
}
void *test_compiled_ptr = dlsym(object_handle, "TestCompiled");
if (!test_compiled)
{
  printf("%s\n", dlerror());
  // Exit or return error code
}

void (*test_compiled)() = (void (*)()) test_compiled_ptr;
test_compiled();

编译时,您需要包含dlfcn.h并与-ldl相关联。

这与您现在正在做的事情之间的区别在于您正在加载库静态而不是动态。即使共享对象是动态链接库,&#34;因为它们是在windows世界中调用的,所以按照现在的方式执行它是在程序启动时加载对象中的所有符号。要在运行时动态加载某些符号,您需要这样做。

答案 1 :(得分:0)

我复制了解决问题的answer from the RootTalk forum的重点,以供参考:

关键是ROOT(CINT)的C解释器需要一个&#34; CINT字典&#34;用于外部编译的功能。 (通过ROOT编译时没有问题,因为ACLiC在预编译宏[root TestCompiled.C++]时创建了这个字典。)

因此,必须创建一个接口TestCompiled.h++

#ifdef __cplusplus
extern "C" {
#endif

  void TestCompiled(void);

#ifdef __cplusplus
} /* end of extern "C" */
#endif

然后必须将该接口与共享对象一起加载到ROOT中:

{ // Test.C ROOT/CINT unnamed macro (interpreted)
  Int_t check, error;
  check = gROOT->LoadMacro("TestCompiled_C.so", &error);
  std::cout << "_C.so check " << check << " error " << error << std::endl;
  check = gROOT->LoadMacro("TestCompiled.h++", &error);
  std::cout << "_h.so check " << check << " error " << error << std::endl;
  TestCompiled(); // execute the compiled function
}

ROOT现在可以使用外部编译的程序:root -b -l -n -q Test.C有效。

这可以使用例如以下TestCompiled.C上的g ++进行测试:

#include <cstdio>
extern "C" void TestCompiled(void) { printf("test\n"); }

编译
g++ -fPIC -shared -o TestCompiled_C.so TestCompiled.C