template class の実装を別ファイルに分離
導入
普通の CPU 用 (C++) と GPU 用 (CUDA) のコードを宣言(.hpp)とか使い方は共通にして、実装をわけたい。kernel関数とか thrust::device_vector とかは CUDA のコード(*.cu)にしか書けない。
やり方
a.hpp
#pragma once
#include <memory>
template <typename T>
class A {
public:
A();
virtual ~A();
void where();
private:
A(const A&);
const A& operator=(const A&);
struct Impl;
Impl* _impl;
};
// 実体化したい型Tを列挙、ないものはリンク失敗
template class A<float>;
template class A<double>;
a_common.hpp
// CPU, GPU 実装で共通の部分
#include <a.hpp>
template <typename T>
A<T>::A() : _impl(new Impl) {}
template <typename T>
A<T>::~A() { delete _impl; }
template <typename T>
void A<T>::where() { _impl->msg(); }
a.cpp
// CPU 用の実装
#include <iostream>
#include "a_common.hpp"
template <typename T>
struct A<T>::Impl {
void msg() {
std::cout << "from cpp" << std::endl;
}
};
a.cu
// GPU 用の実装
#include <iostream>
#include "a_common.hpp"
template <typename T>
struct A<T>::Impl {
void msg() {
std::cout << "from cuda" << std::endl;
}
};
#pragma once
#include <memory>
template <typename T>
class A {
public:
A();
virtual ~A();
void where();
private:
A(const A&);
const A& operator=(const A&);
struct Impl;
Impl* _impl;
};
// 実体化したい型Tを列挙、ないものはリンク失敗
template class A<float>;
template class A<double>;
// CPU, GPU 実装で共通の部分
#include <a.hpp>
template <typename T>
A<T>::A() : _impl(new Impl) {}
template <typename T>
A<T>::~A() { delete _impl; }
template <typename T>
void A<T>::where() { _impl->msg(); }
// CPU 用の実装
#include <iostream>
#include "a_common.hpp"
template <typename T>
struct A<T>::Impl {
void msg() {
std::cout << "from cpp" << std::endl;
}
};
// GPU 用の実装
#include <iostream>
#include "a_common.hpp"
template <typename T>
struct A<T>::Impl {
void msg() {
std::cout << "from cuda" << std::endl;
}
};
ビルド方法とかは CMake のプロジェクトあげましたので見てください。
https://github.com/ShigekiKarita/CMakeExampleCUDA
$ ./cmk.sh
$ ./build/g++/release/test/test_a_cpu
from cpp
$ ./build/g++/release/test/test_a_gpu
from cuda
理由
ググるとこういうのがでます。前者や後者のメソッド 2, 3 はGPU用の .cu ファイルを不適ですが、。
後者のメソッド 1 は使えそうですが、最適化 "-O" オプションによってリンクが通らなくなりました。
これはいけるんですが、全メソッド書くのが面倒ですので宣言 class だけで十分、メンバもCPU/GPUで変えたいので pimpl にしました。
補足
今年リリースされた CUDA 7.0 ではついに C++11 が利用可能になりました。つまり上記 pimpl などの生ポインタを使う部分をスマートポインタで置き換え可能になり、オーバーヘッドなしでメモリ管理でき、記述量が減ります (他にも thrust で頻出のファンクタもラムダにできますね)。CMake では次のように C++11 を nvcc に設定します。
set(CUDA_NVCC_FLAGS "-std=c++11")
Author And Source
この問題について(template class の実装を別ファイルに分離), 我々は、より多くの情報をここで見つけました https://qiita.com/kari_tech/items/42a5d342b6f4854a215f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .