【问题标题】:Unable to decipher nvlink error无法破译 nvlink 错误
【发布时间】:2023-03-27 06:49:01
【问题描述】:

我正在尝试使用nvcc 构建一个项目。我收到了我见过的最烦人的nvlink error: 消息。

这里是链接声明:

nvcc    -rdc=true -arch=sm_21 -O3 -Xcompiler -fPIC -I"/usr/local/ACE_wrappers" -I"/usr/local/ACE_wrappers/TAO" -I"/usr/local/DDS" -I"/usr/include/Qt" -I"/usr/include/QtCore" -I"/usr/include/QtGui" -I"../../include" -I"../../include/DDS" -I"../../include/CoordinateTransforms" -I"../../include/DDS/IDLBrokerTemplates" -I"../../def/IDL" -I"../../def/CMD" -I"../../def/XSD" -I"../../src/NetAcquire" -I"/usr/local/ACE_wrappers/TAO/orbsvcs" -I"/usr/local/include/lct.7.5.4" -L"." -L"/usr/local/ACE_wrappers/lib" -L"/usr/local/DDS/lib" -L"/usr/lib64" -L"/usr/local/lib64" -L"../../def/IDL/lib" -L"../../def/XSD" -L"/usr/local/lib" .obj/../../src/Component.o .obj/../../src/COM.o .obj/../../src/DDS/EntityManager.o .obj/../../src/IDLBrokerTemplates/CommandManager.o .obj/../../src/IDLBrokerTemplates/OptionManager.o .obj/../../include/ApplicationProcessStateReporter_moc.o .obj/../../src/Application.o .obj/../../src/CoordinateTransforms/Site.o .obj/../../src/CoordinateTransforms/Geodesy.o .obj/../../src/CoordinateTransforms/Earth.o .obj/../../src/CoordinateTransforms/StateVector.o .obj/../../src/CoordinateTransforms/KeplerianImpact.o .obj/../../src/CoordinateTransforms/GeodeticPosition.o .obj/../../src/IDLBrokerTemplates/MeasurandSubscription.o .obj/../../src/NetAcquire/NetAcquire.o .obj/DataLossFlightTimeImpl.o .obj/DataLossFlightTime.o .obj/DftTable.o .obj/OptionListener.o .obj/PrimaryListener.o .obj/MissionTimeListener.o .obj/DeadMan.o .obj/main.o .obj/../../src/XML/spline.o .obj/../../src/XML/FpTable.o -l"naps-x86_64" -l"naio-x86_64" -l"nalct-x86_64" -l"curl" -l"TAO_Messaging" -l"TAO_Valuetype" -l"TAO_PI_Server" -l"TAO_PI" -l"TAO_CodecFactory" -l"TAO_CosNaming" -l"armadillo" -l"boost_filesystem" -l"boost_system" -l"xerces-c" -l"jarssXSD" -l"OpenDDS_Tcp" -l"JARSSRTv10" -l"QtNetwork" -l"fontconfig" -l"QtGui" -l"QtCore" -l"OpenDDS_Rtps_Udp" -l"OpenDDS_Rtps" -l"OpenDDS_Multicast" -l"OpenDDS_Udp" -l"OpenDDS_InfoRepoDiscovery" -l"OpenDDS_Dcps" -l"TAO_PortableServer" -l"TAO_AnyTypeCode" -l"TAO" -l"ACE"  -o "DFT"

我得到了

nvlink error   : Undefined reference to '_ZN5JARSS15KeplerianImpactC1ERKdS2_S2_S2_S2_S2_'
nvlink error   : Undefined reference to '_ZNK5JARSS15KeplerianImpact9getStatusEv'
nvlink error   : Undefined reference to '_ZNK5JARSS15KeplerianImpact13getImpactTimeEv'
nvlink error   : Undefined reference to '_ZNK5JARSS15KeplerianImpact11getPlhStateEv'
nvlink error   : Undefined reference to '_ZN5JARSS15KeplerianImpactD1Ev'
nvlink error   : Undefined reference to '_ZN5JARSS7Geodesy12EFG2GeodeticERKdS2_S2_PdS3_S3_'

我确定这些函数/文件包含在编译中。您可以从编译中看到KeplerianImpact.cppGeodesy.cpp 在那里。

有什么方法可以让链接输出更容易阅读,以便我可以调试它?

【问题讨论】:

  • 如果您的 .cpp 文件中有 nvlink 需要的设备代码,那就有问题了。我在编译命令中只能看到KeplerianImpact.oGeodesy.o,所以我不知道,只是根据你的说法。
  • 我在 Geodesy 需要的 cpp 代码中有我需要的 __constant__ 值。不过,所有 Geodesy 代码均已编译 __host__ __device__。常量的位置有影响吗?
  • 是的。默认情况下,nvcc 会忽略 .cpp 文件中的任何代码,并将整个文件交给主机编译器。但是,我不确定您的情况发生了什么,因为主机编译器应该在 __constant__ 构造上窒息。 (它也应该在__host__ __device__ 上窒息)。不过,如果这是针对设备的,并且位于 .cpp 文件中,则可能会导致链接问题。
  • 如果定义了__CUDACC__,我将__constant__, __host____device__ 定义为空。这(我认为)将允许我对 cpp 和 cu 文件使用相同的类和定义。我将通过更改扩展来尝试一个实验,并告诉你它是如何进行的。
  • 糟糕,我的意思是“如果__CUDACC__ 定义。

标签: cuda nvcc


【解决方案1】:

使用c++filt 对名称进行分解。例如:

$ c++filt _ZN5JARSS15KeplerianImpactC1ERKdS2_S2_S2_S2_S2_ JARSS::KeplerianImpact::KeplerianImpact(double const&, double const&, double const&, double const&, double const&, double const&)

【讨论】:

    【解决方案2】:

    之前遇到过这个问题,我猜你没有使用设备链接器链接设备对象。

    如下所示,通过编译为设备生成可重定位代码(-dc 是 -c 的设备等价物,有关详细信息,请参阅manual

    nvcc –arch=sm_21 –dc a.cu b.cu
    

    通过在最终主机链接之前调用 nvlink 或 dlink 来链接代码的设备部分

    nvlink -arch=sm_21 a.o b.o -o link.o (or)
    nvcc –arch=sm_21 –dlink a.o b.o –o link.o
    

    最后使用宿主编译器形成可执行文件,

    g++ a.o b.o link.o –L<path> -lcudart
    

    【讨论】:

      【解决方案3】:

      我想通了。

      我需要在正确的文件中定义我的函数。比如在Foo.h:

      class Foo {
      public:
          __host__ __device__
          Foo();
      }
      

      Foo.cu中的函数定义不是 Foo.cpp中的函数,正如我最初所想的那样。

       Foo::Foo() {}
      

      对于常量变量,我需要实施稍微不同的策略。

      这是我开始使用的 C++ 类的示例:

      class Foo {
      public:
          static double const epsilon;
          static void functionThatUsesEpsilon();
          /**/
      }
      

      必须转换为使用全局命名空间作为 epsilon def'n

      namespace foo {
          extern __constant__ double epsilon;
      } 
      
      class Foo {
      public:
          // same stuff as before with the addition of this function
          __host__ __device__
          static inline double getEpsilon() {
      #ifdef __CUDACC__
               return foo::epsilon;
      #else
               return epsilon;
      #endif
          }  
      
          static void functionThatUsesEpsilon() {
              if (bar < getEpsilon()) { // etc }
          }
      };
      

      上面的ifdef 将为主机或设备代码返回正确版本的变量。我引用Foo::epsilon 的所有地方都需要替换为Foo::getEpsilon(),以便返回正确的epsilon。

      希望这对将来的某人有所帮助。感谢@RobertCrovella 让我思考。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-31
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 2016-09-27
        • 1970-01-01
        相关资源
        最近更新 更多