0

I found that cuda support use "template" keyword for the code, now I would like to link the usage of "template" between nvcc and g++. But it seems that I cannot find a proper way to implement it, so I use the string of datatype to deliever the datatype declaration. Could I find a better method to do it?

//in .cpp

extern "C" void function(string T);

int main(){
    function("float");
}

//in .cu

extern "C" void function(string T){
    if(T == "short")
        func<short>(...);
    if(T == "int")
        func<int>(...);
    .......
}
talonmies
  • 70,661
  • 34
  • 192
  • 269
Lekayef
  • 11
  • 4
  • I thought this way is functional, but I hope to find a more efficient and more elegant way to do the same thing, thanks a lot ! – Lekayef Apr 19 '19 at 02:55
  • 1
    This reads like an X-Y question. Templates are fully supported and it should be trivial to fix whatever your original problem was rather than try an invent some sort of ridiculous scheme to replace it. As a tip, start by losing the C linkage on everything. C++ linkage is fully supported in CUDA and if you are using templates, you need to use C++ linkage – talonmies Apr 19 '19 at 06:42
  • if you have a solution to share, add it ad an answer. Don't edit it into your question – talonmies Apr 19 '19 at 12:31

1 Answers1

0

You could use C-style function overloading.

// in .cpp

extern "C" void func_short();
extern "C" void func_int();
extern "C" void func_float();

int main(){
  func_float();
}

// in .cu

template <typename T>
void func() {
  // ...
}

extern "C" void func_short() {
  func<short>();
}

extern "C" void func_int() {
  func<int>();
}

extern "C" void func_float() {
  func<float>();
}

This is significantly faster than comparing strings every time you call the function. If you wanted to, you could create a wrapper template function on the C++ side to make the usage a bit cleaner.

// in .cpp

extern "C" void func_short();
extern "C" void func_int();
extern "C" void func_float();

template <typename T>
void func() = delete;

template <>
void func<short>() {
  func_short();
}

template <>
void func<int>() {
  func_int();
}

template <>
void func<float>() {
  func_float();
}

int main(){
  func<float>();
}

To make maintenance a little easier, you could define some macros.

// in .cpp

template <typename T>
void func() = delete;

#define DECLARE_FUNC(TYPE)                                                      \
  extern "C" void func_##TYPE();                                                \
  template <>                                                                   \
  void func<TYPE>() {                                                           \
    func_##TYPE();                                                              \
  }                                                                             \

DECLARE_FUNC(short)
DECLARE_FUNC(int)
DECLARE_FUNC(float)

int main(){
  func<float>();
}

//in .cu

template <typename T>
void func() {
  // ...
}

#define DECLARE_FUNC(TYPE)                                                      \
  extern "C" void func_##TYPE() {                                               \
    func<TYPE>();                                                               \
  }

DECLARE_FUNC(short)
DECLARE_FUNC(int)
DECLARE_FUNC(float)

You could put those DECLARE_FUNC lines in a common header so that you only have to update the list in one place. If you wanted to add a double function, you could just add DECLARE_FUNC(double) to the header.

// in declare_func.hpp

DECLARE_FUNC(short)
DECLARE_FUNC(int)
DECLARE_FUNC(float)

// in .cpp

template <typename T>
void func() = delete;

#define DECLARE_FUNC(TYPE)                                                      \
  extern "C" void func_##TYPE();                                                \
  template <>                                                                   \
  void func<TYPE>() {                                                           \
    func_##TYPE();                                                              \
  }                                                                             \

#include "declare_func.hpp"

int main(){
  func<float>();
}

//in .cu

template <typename T>
void func() {
  // ...
}

#define DECLARE_FUNC(TYPE)                                                      \
  extern "C" void func_##TYPE() {                                               \
    func<TYPE>();                                                               \
  }

#include "declare_func.hpp"

I've gone from easy-to-setup to easy-to-maintain. You'll have to decide what is appropriate for your situation.

Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50
  • that is what I desired for. Thanks. And what if I have a lot of functions, like, I have func1, func2, func3, etc. with templates, Could I do the same thing by using macros or other way? – Lekayef Apr 19 '19 at 06:03