如何 thrust::make_transform_iterator 取消引用 device_ptr?
How to thrust::make_transform_iterator that dereferences a device_ptr?
C++ 和 CUDA 的新手。
使用 MSVS 2015 社区和 CUDA 9.2。
我尝试制作一个 transform_iterator 只是取消引用 device_ptr。
我收到编译错误:函数 "dereference_device_double_functor::operator()" 无法使用给定的参数列表
调用
我还制作了一个使用 host_vector 和普通双指针的版本,以确保我的仿函数使用正确。
#include <iostream>
#include "thrust\device_vector.h"
#include "thrust\host_vector.h"
struct dereference_device_double_functor
{
dereference_device_double_functor() {}
typedef thrust::device_reference<thrust::device_ptr<double>> argument_type;
typedef double result_type;
__host__ __device__
double operator()(thrust::device_reference<thrust::device_ptr<double>> xDpRef) const {
thrust::device_ptr<double> xDp = (thrust::device_ptr<double>)xDpRef;
return *xDp;
}
};
struct dereference_host_double_functor
{
dereference_host_double_functor() {}
typedef double* argument_type;
typedef double result_type;
__host__ __device__
double operator()(double* const& xPtr) const {
return *xPtr;
}
};
int main()
{
// Create double
thrust::device_vector<double> dv(1, 5);
thrust::host_vector<double> hv(1, 6);
// Make sure its there
std::cout << dv[0] << std::endl;
std::cout << hv[0] << std::endl;
// Create pointers to doubles
thrust::device_vector<thrust::device_ptr<double>> dvPtr(1);
thrust::device_vector<double*> hvPtr(1);
// Assign pointers to doubles
dvPtr[0] = &(dv[0]);
hvPtr[0] = &(hv[0]);
// Make sure pointers point correctly
std::cout << *((thrust::device_ptr<double>)dvPtr[0]) << std::endl;
std::cout << *(hvPtr[0]) << std::endl;
// Test functor with iterator
auto dvi = dvPtr.begin();
double dvd = dereference_device_double_functor()(*dvi);
auto hvi = hvPtr.begin();
double hvd = dereference_host_double_functor()(*hvi);
// Make sure it worked with iterator
std::cout << dvd << std::endl;
std::cout << hvd << std::endl;
// Make dereferencing transfom iterators
auto tik = thrust::make_transform_iterator(dvPtr.begin(), dereference_device_double_functor());
auto tij = thrust::make_transform_iterator(hvPtr.begin(), dereference_host_double_functor());
// Check that transform iterators work
//std::cout << *tik << std::endl; // Will cause compile error: function "dereference_device_double_functor::operator()" cannot be called with the given argument list
std::cout << *tij << std::endl;
return 0;
}
感谢您的帮助!
在你的问题中,你这样说:
I tried making a transform_iterator that just dereferences a device_ptr.
然而,这不是我在您的代码中看到的:
__host__ __device__
double operator()(thrust::device_reference<thrust::device_ptr<double>> xDpRef) const {
当我在 linux 上编译你的代码时,我得到以下信息(摘自编译错误喷涌):
$ nvcc -std=c++11 -o t351 t351.cu
/usr/local/cuda/bin/..//include/thrust/iterator/transform_iterator.h(312): error: function "dereference_device_double_functor::operator()" cannot be called with the given argument list
argument types are: (thrust::device_ptr<double>)
object type is: dereference_device_double_functor
...
所以推力超过了你 thrust::device_ptr<double>
。但是您的仿函数运算符配置为采用 thrust::device_reference<thrust::device_ptr<double>>
当我修改你的代码时:
__host__ __device__
double operator()(thrust::device_reference<thrust::device_ptr<double>> xDpRef) const {
对此:
__host__ __device__
double operator()(thrust::device_ptr<double> xDpRef) const {
它为我正确编译和运行(linux):
$ cat t351.cu
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
struct dereference_device_double_functor
{
dereference_device_double_functor() {}
typedef thrust::device_reference<thrust::device_ptr<double>> argument_type;
typedef double result_type;
__host__ __device__
double operator()(thrust::device_ptr<double> xDpRef) const {
thrust::device_ptr<double> xDp = (thrust::device_ptr<double>)xDpRef;
return *xDp;
}
};
struct dereference_host_double_functor
{
dereference_host_double_functor() {}
typedef double* argument_type;
typedef double result_type;
__host__ __device__
double operator()(double* const& xPtr) const {
return *xPtr;
}
};
int main()
{
// Create double
thrust::device_vector<double> dv(1, 5);
thrust::host_vector<double> hv(1, 6);
// Make sure its there
std::cout << dv[0] << std::endl;
std::cout << hv[0] << std::endl;
// Create pointers to doubles
thrust::device_vector<thrust::device_ptr<double>> dvPtr(1);
thrust::device_vector<double*> hvPtr(1);
// Assign pointers to doubles
dvPtr[0] = &(dv[0]);
hvPtr[0] = &(hv[0]);
// Make sure pointers point correctly
std::cout << *((thrust::device_ptr<double>)dvPtr[0]) << std::endl;
std::cout << *(hvPtr[0]) << std::endl;
// Test functor with iterator
auto dvi = dvPtr.begin();
double dvd = dereference_device_double_functor()(*dvi);
auto hvi = hvPtr.begin();
double hvd = dereference_host_double_functor()(*hvi);
// Make sure it worked with iterator
std::cout << dvd << std::endl;
std::cout << hvd << std::endl;
// Make dereferencing transfom iterators
auto tik = thrust::make_transform_iterator(dvPtr.begin(), dereference_device_double_functor());
auto tij = thrust::make_transform_iterator(hvPtr.begin(), dereference_host_double_functor());
// Check that transform iterators work
std::cout << *tik << std::endl; // Will cause compile error: function "dereference_device_double_functor::operator()" cannot be called with the given argument list
std::cout << *tij << std::endl;
return 0;
}
$ nvcc -std=c++11 -o t351 t351.cu
$ cuda-memcheck ./t351
========= CUDA-MEMCHECK
5
6
5
6
5
6
5
6
========= ERROR SUMMARY: 0 errors
$
C++ 和 CUDA 的新手。 使用 MSVS 2015 社区和 CUDA 9.2。
我尝试制作一个 transform_iterator 只是取消引用 device_ptr。
我收到编译错误:函数 "dereference_device_double_functor::operator()" 无法使用给定的参数列表
调用我还制作了一个使用 host_vector 和普通双指针的版本,以确保我的仿函数使用正确。
#include <iostream>
#include "thrust\device_vector.h"
#include "thrust\host_vector.h"
struct dereference_device_double_functor
{
dereference_device_double_functor() {}
typedef thrust::device_reference<thrust::device_ptr<double>> argument_type;
typedef double result_type;
__host__ __device__
double operator()(thrust::device_reference<thrust::device_ptr<double>> xDpRef) const {
thrust::device_ptr<double> xDp = (thrust::device_ptr<double>)xDpRef;
return *xDp;
}
};
struct dereference_host_double_functor
{
dereference_host_double_functor() {}
typedef double* argument_type;
typedef double result_type;
__host__ __device__
double operator()(double* const& xPtr) const {
return *xPtr;
}
};
int main()
{
// Create double
thrust::device_vector<double> dv(1, 5);
thrust::host_vector<double> hv(1, 6);
// Make sure its there
std::cout << dv[0] << std::endl;
std::cout << hv[0] << std::endl;
// Create pointers to doubles
thrust::device_vector<thrust::device_ptr<double>> dvPtr(1);
thrust::device_vector<double*> hvPtr(1);
// Assign pointers to doubles
dvPtr[0] = &(dv[0]);
hvPtr[0] = &(hv[0]);
// Make sure pointers point correctly
std::cout << *((thrust::device_ptr<double>)dvPtr[0]) << std::endl;
std::cout << *(hvPtr[0]) << std::endl;
// Test functor with iterator
auto dvi = dvPtr.begin();
double dvd = dereference_device_double_functor()(*dvi);
auto hvi = hvPtr.begin();
double hvd = dereference_host_double_functor()(*hvi);
// Make sure it worked with iterator
std::cout << dvd << std::endl;
std::cout << hvd << std::endl;
// Make dereferencing transfom iterators
auto tik = thrust::make_transform_iterator(dvPtr.begin(), dereference_device_double_functor());
auto tij = thrust::make_transform_iterator(hvPtr.begin(), dereference_host_double_functor());
// Check that transform iterators work
//std::cout << *tik << std::endl; // Will cause compile error: function "dereference_device_double_functor::operator()" cannot be called with the given argument list
std::cout << *tij << std::endl;
return 0;
}
感谢您的帮助!
在你的问题中,你这样说:
I tried making a transform_iterator that just dereferences a device_ptr.
然而,这不是我在您的代码中看到的:
__host__ __device__
double operator()(thrust::device_reference<thrust::device_ptr<double>> xDpRef) const {
当我在 linux 上编译你的代码时,我得到以下信息(摘自编译错误喷涌):
$ nvcc -std=c++11 -o t351 t351.cu
/usr/local/cuda/bin/..//include/thrust/iterator/transform_iterator.h(312): error: function "dereference_device_double_functor::operator()" cannot be called with the given argument list
argument types are: (thrust::device_ptr<double>)
object type is: dereference_device_double_functor
...
所以推力超过了你 thrust::device_ptr<double>
。但是您的仿函数运算符配置为采用 thrust::device_reference<thrust::device_ptr<double>>
当我修改你的代码时:
__host__ __device__
double operator()(thrust::device_reference<thrust::device_ptr<double>> xDpRef) const {
对此:
__host__ __device__
double operator()(thrust::device_ptr<double> xDpRef) const {
它为我正确编译和运行(linux):
$ cat t351.cu
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
struct dereference_device_double_functor
{
dereference_device_double_functor() {}
typedef thrust::device_reference<thrust::device_ptr<double>> argument_type;
typedef double result_type;
__host__ __device__
double operator()(thrust::device_ptr<double> xDpRef) const {
thrust::device_ptr<double> xDp = (thrust::device_ptr<double>)xDpRef;
return *xDp;
}
};
struct dereference_host_double_functor
{
dereference_host_double_functor() {}
typedef double* argument_type;
typedef double result_type;
__host__ __device__
double operator()(double* const& xPtr) const {
return *xPtr;
}
};
int main()
{
// Create double
thrust::device_vector<double> dv(1, 5);
thrust::host_vector<double> hv(1, 6);
// Make sure its there
std::cout << dv[0] << std::endl;
std::cout << hv[0] << std::endl;
// Create pointers to doubles
thrust::device_vector<thrust::device_ptr<double>> dvPtr(1);
thrust::device_vector<double*> hvPtr(1);
// Assign pointers to doubles
dvPtr[0] = &(dv[0]);
hvPtr[0] = &(hv[0]);
// Make sure pointers point correctly
std::cout << *((thrust::device_ptr<double>)dvPtr[0]) << std::endl;
std::cout << *(hvPtr[0]) << std::endl;
// Test functor with iterator
auto dvi = dvPtr.begin();
double dvd = dereference_device_double_functor()(*dvi);
auto hvi = hvPtr.begin();
double hvd = dereference_host_double_functor()(*hvi);
// Make sure it worked with iterator
std::cout << dvd << std::endl;
std::cout << hvd << std::endl;
// Make dereferencing transfom iterators
auto tik = thrust::make_transform_iterator(dvPtr.begin(), dereference_device_double_functor());
auto tij = thrust::make_transform_iterator(hvPtr.begin(), dereference_host_double_functor());
// Check that transform iterators work
std::cout << *tik << std::endl; // Will cause compile error: function "dereference_device_double_functor::operator()" cannot be called with the given argument list
std::cout << *tij << std::endl;
return 0;
}
$ nvcc -std=c++11 -o t351 t351.cu
$ cuda-memcheck ./t351
========= CUDA-MEMCHECK
5
6
5
6
5
6
5
6
========= ERROR SUMMARY: 0 errors
$