I have a set of C++ wrapper classes that abstract out host and device memory management. Since I upgraded to CUDA toolkit version 3, there are some errors that have come up
Look at the following example code derived from the original classes and simplified to the simplest case:
#include <iostream>
using namespace std;
template <class T>
class TArray
{
public:
T i;
TArray(){}
virtual bool isDeviceBuf(void) const = 0;
template<typename T2> void assign(const T2 &other)
{
if(isDeviceBuf())
{
if(other.isDeviceBuf())
{
cerr << "Device To Device" << endl;
}
else
{
cerr << "Host To Device" << endl;
}
}
else
{
if(other.isDeviceBuf())
{
cerr << "Device To Host" << endl;
}
else
{
cerr << "Host To Host" << endl;
}
}
}
//////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////
template <class T>
class TCArray : public TArray<T>
{
public:
bool isDeviceBuf(void) const
{
return false;
}
TCArray(){}
explicit TCArray(const TCArray &that)
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
explicit TCArray(const TArray<T> &that) : TArray<T>()
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
// Default = operator has to be overridden
void operator=(const TCArray &that)
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
void operator=(const TArray<T> &that)
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////
template <class T>
class TGArray : public TArray<T>
{
public:
TGArray(){}
bool isDeviceBuf(void) const
{
return true;
}
explicit TGArray(const TGArray &that)
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
explicit TGArray(const TArray<T> &that) : TArray<T>()
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
// Default = operator has to be overridden
void operator=(const TGArray &that)
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
void operator=(const TArray<T> &that)
{
assign(that);
}
//////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////
int main()
{
TCArray<int> a, b;
TGArray<int> c, d;
a = b;
a = c;
c = a;
c = d;
TCArray<int> a1(a), b1(c);
TGArray<int> c1(c), d1(a);
return 0;
}
I compiled this with Visual Studio 2008, cygwin gcc (version 3.4), gcc 4.3 on Ubuntu
All compile perfectly and the output shown is :
[font=“Courier New”]Host To Host
Device To Host
Host To Device
Device To Device
Host To Host
Device To Host
Device To Device
Host To Device
[/font]
showing the right behaviour
compiling with nvcc on windows :
C:\Data\Proj\test\cuda>nvcc testvirt.cu
testvirt.cu
tmpxft_000005f4_00000000-3_testvirt.cudafe1.gpu
tmpxft_000005f4_00000000-8_testvirt.cudafe2.gpu
testvirt.cu
tmpxft_000005f4_00000000-3_testvirt.cudafe1.cpp
tmpxft_000005f4_00000000-13_testvirt.ii
tmpxft_000005f4_00000000-14_testvirt.obj : error LNK2019: unresolved external symbol "public: virtual bool __thiscall TArray<int>::i
sDeviceBuf(void)const " (?isDeviceBuf@?$TArray@H@@UBE_NXZ) referenced in function "public: void __thiscall TArray<int>::assign<class
TArray<int> >(class TArray<int> const &)" (??$assign@V?$TArray@H@@@?$TArray@H@@QAEXABV0@@Z)
a.exe : fatal error LNK1120: 1 unresolved externals
A similar error results on Linux.
The workaround is to use a pointer parameter rather than a reference for the assign() function :
template <class T>
class TArray
{
public:
T i;
TArray(){}
virtual bool isDeviceBuf(void) const = 0;
template<typename T2> void assign(const T2 *other)
{
if(isDeviceBuf())
{
if(other->isDeviceBuf())
{
cerr << "Device To Device" << endl;
}
else
{
cerr << "Host To Device" << endl;
}
}
else
{
if(other->isDeviceBuf())
{
cerr << "Device To Host" << endl;
}
else
{
cerr << "Host To Host" << endl;
}
}
}
//////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////
template <class T>
class TCArray : public TArray<T>
{
public:
bool isDeviceBuf(void) const
{
return false;
}
TCArray(){}
explicit TCArray(const TCArray &that)
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
explicit TCArray(const TArray<T> &that) : TArray<T>()
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
// Default = operator has to be overridden
void operator=(const TCArray &that)
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
void operator=(const TArray<T> &that)
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////
template <class T>
class TGArray : public TArray<T>
{
public:
TGArray(){}
bool isDeviceBuf(void) const
{
return true;
}
explicit TGArray(const TGArray &that)
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
explicit TGArray(const TArray<T> &that) : TArray<T>()
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
// Default = operator has to be overridden
void operator=(const TGArray &that)
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
void operator=(const TArray<T> &that)
{
assign(&that);
}
//////////////////////////////////////////////////////////////////////////
};
This is clearly a failure to compile correct C++ code.