LoginSignup
16
13

More than 5 years have passed since last update.

template class の実装を別ファイルに分離

Last updated at Posted at 2015-04-02

導入

普通の 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;
    }
};

ビルド方法とかは CMake のプロジェクトあげましたので見てください。

https://github.com/ShigekiKarita/CMakeExampleCUDA

実行結果.txt
$ ./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 に設定します。

CMakeLists.txt
set(CUDA_NVCC_FLAGS "-std=c++11")
16
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
13