1

次の些細な削除機能を使用

struct CudaDeleter{ void operator()(void * ptr) { cudaFree( ptr ); } };

nvccでコンパイルされたコードでdeleterを使用すると、次のエラーが発生します。同じデリータがvs2012コンパイラで正常に動作します

warning : "std::unique_ptr<_Ty, _Dx>::unique_ptr(
const std::unique_ptr<_Ty, _Dx>::_Myt &)
[with _Ty=const int, _Dx=cuda::CudaDeleter]"

error : function "cuda::CudaDeleter::operator()"
cannot be called with the given argument list

warning : "std::unique_ptr<_Ty, _Dx>::unique_ptr(
const std::unique_ptr<_Ty, _Dx>::_Myt &)
[with _Ty=float, _Dx=cuda::CudaDeleter]"

@talonmies:スマートポインタはこの関数のみで構築されます

template <typename T>
std::unique_ptr<T, CudaDeleter> make_unique(size_t size)
{
    void * pMemory = nullptr;
    check( cudaMalloc(&pMemory, size) );
    return std::unique_ptr<T, CudaDeleter>( static_cast<T*>(pMemory) );
}
4

2 に答える 2

5

以下は私にとってはうまくいきます。以下のスタンドアロン コードを試してみてください。動作する場合は、コードとの違いを特定する必要があります。そうでない場合は、セットアップに何か違いがあります。

#include <iostream>
#include <memory>

struct CudaDeleter
{
    void operator()(void *p)
    {
        std::cout << "Free..." << std::endl;
        cudaError_t res = cudaFree(p);
        if (res != cudaSuccess)
        {
            std::cout << "Error freeing: " << cudaGetErrorString(res) << std::endl;
        }
    }
};

template <typename T>
std::unique_ptr<T, CudaDeleter> make_unique(size_t size)
{
    void *pMemory = nullptr;
    std::cout << "Allocate..." << std::endl;
    cudaError_t res = cudaMalloc(&pMemory, size);
    if (res != cudaSuccess)
    {
        std::cout << "Error allocating pMemory: " << cudaGetErrorString(res) << std::endl;
        throw;
    }
    return std::unique_ptr<T, CudaDeleter>(static_cast<T*>(pMemory));
}

int main(void)
{
    {
        std::cout << "Create..." << std::endl;
        std::unique_ptr<float, CudaDeleter> x = make_unique<float>(100*sizeof(float));
        std::cout << "Destroy..." << std::endl;
    }
    std::cout << "Done." << std::endl;
}
于 2013-02-19T17:38:11.757 に答える
0

私が抱えていた問題を発見しました。結局、それは私の側の間違いでした

T * を void * にキャストできないわけではありませんが、const T * を void * にキャストすることはできません。

さらに、const へのポインタは cudaFree では解放できません。つまり、Eric の提案は

template<class T> struct CudaDeleter{ void operator()(T* ptr){...}}

動作しないでしょう。

このようなものは機能しますが

template <typename T>
std::unique_ptr<typename std::remove_const<T>::type, CudaDeleter> make_unique(size_t size)
{
    typename std::remove_const<T>::type * pMemory = nullptr;
    check( cudaMalloc(&pMemory, size) );
    return std::unique_ptr<typename std::remove_const<T>::type, CudaDeleter>( pMemory );
}
于 2013-02-20T08:14:38.627 に答える