Nested container and template problem

I’m trying to create own map over unordered_map, but I’m having problems when compiling this using nvcc.

//foo.h

#include <iostream>

#include <tr1/unordered_map>

using std::string;

using std::tr1::unordered_map;

class MyMap: public unordered_map< string, int > {

  public:

	void myAdd( string, int );

	void myRemove( string );

  private:

	int adds, removes;

};
//foo.cc

#include <foo.h>

void MyMap::myAdd( string key, int value)

{

  operator[]( key ) = value;

  adds++; // Just to have some reason to make own function

}

void MyMap::myRemove( string key)

{

  erase( find( key ) );

  removes++; // Just to have some reason to make own function

}
//test.cu or test.cc

#include <foo.h>

using std::cout;

using std::endl;

int main( void )

{

  MyMap myMap;

  myMap.myAdd("test0", 0);

  myMap.myAdd("test1", 1);

  myMap.myAdd("test2", 2);

  myMap.myRemove("test1");

  cout << myMap.size() << endl;

}

if the last one is named test.cc I have no problem compiling

$ nvcc -I. test.cc foo.cc -o test.out

I would like to call cuda kernel from the same function where I’m using this container, so I have named the file as test.cu.

I’m expecting that nvcc would splits the code to device and host codes and this all should be still compiled with g++, but I’m getting this error

$ nvcc -I. test.cu foo.cc -o b.out

/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/tr1/hashtable(1041): error: too few template parameters -- does not match previous declaration

		  detected during:

			instantiation of class "std::tr1::hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, cache_hash_code, constant_iterators, unique_keys> [with Key=std::string, Value=std::pair<const std::string, int>, Allocator=std::allocator<std::pair<const std::string, int>>, ExtractKey=Internal::extract1st<std::pair<const std::string, int>>, Equal=std::equal_to<std::string>, H1=std::tr1::hash<std::string>, H2=Internal::mod_range_hashing, H=Internal::default_ranged_hash, RehashPolicy=Internal::prime_rehash_policy, cache_hash_code=false, constant_iterators=false, unique_keys=true]" 

/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/tr1/unordered_map(58): here

			instantiation of class "std::tr1::unordered_map<Key, T, Hash, Pred, Alloc, cache_hash_code> [with Key=std::string, T=int, Hash=std::tr1::hash<std::string>, Pred=std::equal_to<std::string>, Alloc=std::allocator<std::pair<const std::string, int>>, cache_hash_code=false]" 

./foo.h(8): here

1 error detected in the compilation of "/tmp/tmpxft_0000401a_00000000-4_test.cpp1.ii"

.

The basic system info:

$ nvcc --version					 

nvcc: NVIDIA (R) Cuda compiler driver

Copyright (c) 2005-2009 NVIDIA Corporation

Built on Thu_Apr__9_05:05:52_PDT_2009

Cuda compilation tools, release 2.2, V0.2.1221

$ g++ --version

g++ (GCC) 4.1.2 (Gentoo 4.1.2 p1.0.2)

Copyright (C) 2006 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ uname -a

Linux noname 2.6.25-gentoo-r7 #5 SMP Wed Dec 10 00:37:51 JST 2008 x86_64 AMD Athlon(tm) 64 X2 Dual Core Processor 6000+ AuthenticAMD GNU/Linux

Any ideas and comments are appreciated.

jared@filthy:~/dev/p4/research/research/jhoberock/src/bugs$ /usr/local/cuda/bin/nvcc -I. test.cc foo.cc -o test.out; ./test.out

2

jared@filthy:~/dev/p4/research/research/jhoberock/src/bugs$ /usr/local/cuda/bin/nvcc --version; echo; gcc --version

nvcc: NVIDIA (R) Cuda compiler driver

Copyright (c) 2005-2009 NVIDIA Corporation

Built on Thu_Apr__9_07:37:20_PDT_2009

Cuda compilation tools, release 2.2, V0.2.1221

gcc (Ubuntu 4.3.2-1ubuntu12) 4.3.2

Copyright (C) 2008 Free Software Foundation, Inc.

This is free software; see the source for copying conditions.  There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Your code seems to build OK for me on my machine. I wonder if this is a gcc issue? It looks like the version you’re using is fairly old. Have you tried running your code through gcc without nvcc?

Thank you from your answer. Yes in case you are compiling it as .cc file it compiles jsut fine because it goes straight to gcc

$ nvcc -v test.cc foo.cc -o test.out

#$ _SPACE_= 

#$ _MODE_=DEVICE

#$ _HERE_=/opt/cuda/bin

#$ _THERE_=/opt/cuda/bin

#$ TOP=/opt/cuda/bin/..

#$ LD_LIBRARY_PATH=/opt/cuda/bin/../lib:/opt/cuda/bin/../extools/lib:

#$ PATH=/opt/cuda/bin/../open64/bin:/opt/cuda/bin/../bin:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.1.2:/usr/qt/3/bin:/opt/cuda/bin

#$ INCLUDES="-I/opt/cuda/bin/../include" "-I/opt/cuda/bin/../include/cudart"  

#$ LIBRARIES=  "-L/opt/cuda/bin/../lib" -lcudart

#$ CUDAFE_FLAGS=

#$ OPENCC_FLAGS=

#$ PTXAS_FLAGS=

#$ gcc -c -x c++ "-I/opt/cuda/bin/../include" "-I/opt/cuda/bin/../include/cudart"   -I. -m64 -o "/tmp/tmpxft_000046ca_00000000-1_test.o" "test.cc" 

#$ gcc -c -x c++ "-I/opt/cuda/bin/../include" "-I/opt/cuda/bin/../include/cudart"   -I. -m64 -o "/tmp/tmpxft_000046ca_00000000-2_foo.o" "foo.cc" 

#$ g++ -m64 -o "test.out" -Wl,--start-group "/tmp/tmpxft_000046ca_00000000-1_test.o" "/tmp/tmpxft_000046ca_00000000-2_foo.o"   "-L/opt/cuda/bin/../lib" -lcudart -Wl,--end-group

but if you compile it as a .cu file it will not go through cudafe

$ nvcc -v test.cu foo.cc -o test.out

#$ _SPACE_= 

#$ _MODE_=DEVICE

#$ _HERE_=/opt/cuda/bin

#$ _THERE_=/opt/cuda/bin

#$ TOP=/opt/cuda/bin/..

#$ LD_LIBRARY_PATH=/opt/cuda/bin/../lib:/opt/cuda/bin/../extools/lib:

#$ PATH=/opt/cuda/bin/../open64/bin:/opt/cuda/bin/../bin:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.1.2:/usr/qt/3/bin:/opt/cuda/bin

#$ INCLUDES="-I/opt/cuda/bin/../include" "-I/opt/cuda/bin/../include/cudart"  

#$ LIBRARIES=  "-L/opt/cuda/bin/../lib" -lcudart

#$ CUDAFE_FLAGS=

#$ OPENCC_FLAGS=

#$ PTXAS_FLAGS=

#$ gcc -D__CUDA_ARCH__=100 -E -x c++ -DCUDA_NO_SM_12_ATOMIC_INTRINSICS -DCUDA_NO_SM_13_DOUBLE_INTRINSICS -DCUDA_FLOAT_MATH_FUNCTIONS -DCUDA_NO_SM_11_ATOMIC_INTRINSICS  "-I/opt/cuda/bin/../include" "-I/opt/cuda/bin/../include/cudart"   -I. -D__CUDACC__ -C  -include "cuda_runtime.h" -m64 -o "/tmp/tmpxft_000046d6_00000000-4_test.cpp1.ii" "test.cu" 

#$ cudafe --m64 --gnu_version=40102 --diag_error=host_device_limited_call --diag_error=ms_asm_decl_not_allowed -tused  --gen_c_file_name "/tmp/tmpxft_000046d6_00000000-1_test.cudafe1.c" --stub_file_name "/tmp/tmpxft_000046d6_00000000-1_test.cudafe1.stub.c" --stub_header_file_name "/tmp/tmpxft_000046d6_00000000-1_test.cudafe1.stub.h" --gen_device_file_name "/tmp/tmpxft_000046d6_00000000-1_test.cudafe1.gpu" --include_file_name "/tmp/tmpxft_000046d6_00000000-3_test.fatbin.c" "/tmp/tmpxft_000046d6_00000000-4_test.cpp1.ii" 

/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/tr1/hashtable(1041): error: too few template parameters -- does not match previous declaration

		  detected during:

			instantiation of class "std::tr1::hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, cache_hash_code, constant_iterators, unique_keys> [with Key=std::string, Value=std::pair<const std::string, int>, Allocator=std::allocator<std::pair<const std::string, int>>, ExtractKey=Internal::extract1st<std::pair<const std::string, int>>, Equal=std::equal_to<std::string>, H1=std::tr1::hash<std::string>, H2=Internal::mod_range_hashing, H=Internal::default_ranged_hash, RehashPolicy=Internal::prime_rehash_policy, cache_hash_code=false, constant_iterators=false, unique_keys=true]" 

/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/tr1/unordered_map(58): here

			instantiation of class "std::tr1::unordered_map<Key, T, Hash, Pred, Alloc, cache_hash_code> [with Key=std::string, T=int, Hash=std::tr1::hash<std::string>, Pred=std::equal_to<std::string>, Alloc=std::allocator<std::pair<const std::string, int>>, cache_hash_code=false]" 

./foo.h(8): here

1 error detected in the compilation of "/tmp/tmpxft_000046d6_00000000-4_test.cpp1.ii".

# --error 0x200 --

I’m not sure if this is even ment to work.

I got it working by keeping everything related to MyMap on .cc and everything that relates to cuda kernels or calling them to .cu, so I don’t need to get MyMap through cudafe. Still would like to know is my first idea “No, not like this” or “We are still lagging support” way.

When i rename test.cc -> test.cu and recompile, I actually see a different error with gcc 4.3 and both nvcc 2.2 & the 2.3 beta:

jared@filthy:~/dev/p4/research/research/jhoberock/src/bugs$ /usr/local/cuda/bin/nvcc -I. test.cu foo.cc -o test.out

/usr/include/c++/4.3/tr1/type_traits(240): error: invalid alignment value specified by attribute

1 error detected in the compilation of "/tmp/tmpxft_00001c5d_00000000-4_test

I’ve filed a bug report for this error, as this usage ought to compile correctly.

I too had the same issues in this post. I was using GCC 4.1.2, and got the first error (the one with lesser template parameters). I then upgraded GCC to version 4.3.4, and got Jared’s type_traits error. I then dug into one of the online forums (http://software.intel.com/en-us/forums/intel-c-compiler/topic/65041/), and found a hack to get rid of this error. Here is what I did in my code:

#define aligned ignored

#include <tr1/unordered_map>

#undef aligned

I don’t get the compiler errors any more.