Невозможно расшифровать ошибку nvlink

Я пытаюсь построить проект с 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.cpp а также Geodesy.cpp там.

Есть ли способ сделать вывод ссылки проще для чтения, чтобы я мог отладить это?

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() поэтому верный эпсилон был возвращен.

Надеюсь, это поможет кому-то в будущем. Спасибо @RobertCrovella за то, что заставил меня задуматься.

Использование c++filt разобрать имена. Например:

$ C++filter _ZN5JARSS15KeplerianImpactC1ERKdS2_S2_S2_S2_S2_ JARSS::KeplerianImpact::KeplerianImpact(двойное и двойное, двойное и двойное, двойное и

Столкнувшись с этой проблемой ранее, я думаю, вы не связали объект устройства с помощью устройства компоновщика.

Сгенерируйте перемещаемый код для устройства путем компиляции, как показано ниже (-dc - это эквивалент устройства -c, дополнительную информацию см. В руководстве)

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
Другие вопросы по тегам