gpt4 book ai didi

cuda - 常量内存中的推力::device_vector

转载 作者:行者123 更新时间:2023-12-04 07:55:08 29 4
gpt4 key购买 nike

我有一个需要在设备上多次引用的浮点数组,所以我相信存储它的最佳位置是 __ 常量 __ 内存(使用 this reference )。数组(或向量)在初始化时需要在运行时写入一次,但由多个不同的函数读取数百万次,因此每次函数调用不断复制到内核似乎是一个坏主意。

const int n = 32;
__constant__ float dev_x[n]; //the array in question

struct struct_max : public thrust::unary_function<float,float> {
float C;
struct_max(float _C) : C(_C) {}
__host__ __device__ float operator()(const float& x) const { return fmax(x,C);}
};
void foo(const thrust::host_vector<float> &, const float &);

int main() {
thrust::host_vector<float> x(n);
//magic happens populate x
cudaMemcpyToSymbol(dev_x,x.data(),n*sizeof(float));

foo(x,0.0);
return(0);
}

void foo(const thrust::host_vector<float> &input_host_x, const float &x0) {
thrust::device_vector<float> dev_sol(n);
thrust::host_vector<float> host_sol(n);

//this method works fine, but the memory transfer is unacceptable
thrust::device_vector<float> input_dev_vec(n);
input_dev_vec = input_host_x; //I want to avoid this
thrust::transform(input_dev_vec.begin(),input_dev_vec.end(),dev_sol.begin(),struct_max(x0));
host_sol = dev_sol; //this memory transfer for debugging

//this method compiles fine, but crashes at runtime
thrust::device_ptr<float> dev_ptr = thrust::device_pointer_cast(dev_x);
thrust::transform(dev_ptr,dev_ptr+n,dev_sol.begin(),struct_max(x0));
host_sol = dev_sol; //this line crashes
}

我尝试添加一个全局推力::device_vector dev_x(n),但它在运行时也崩溃了,并且会在 __ global __ 内存中而不是 __ constant__ 内存中

如果我只是丢弃推力库,这一切都可以工作,但是有没有办法将推力库与全局变量和设备常量内存一起使用?

最佳答案

好问题!你不能投 __constant__数组就好像它是一个普通的设备指针一样。

我会回答你的问题(在下面一行之后),但首先:这是对 __constant__ 的错误使用,这不是你真正想要的。 CUDA 中的常量缓存针对warp 中跨线程的统一访问进行了优化。这意味着经纱中的所有线程同时访问相同的位置。如果 warp 的每个线程访问不同的常量内存位置,则访问将被序列化。因此,连续线程访问连续内存位置的访问模式将比统一访问慢 32 倍。你真的应该只使用设备内存。如果你需要一次写入数据,但读取它很多次,那么只需使用一个device_vector:初始化它一次,然后多次读取它。

要执行您的要求,您可以使用 thrust::counting_iterator作为 thrust::transform 的输入生成一系列索引到您的 __constant__大批。那么你的仿函数的operator()需要一个 int索引操作数而不是 float value 操作数,并在常量内存中查找。

(请注意,这意味着您的仿函数现在只有 __device__ 代码。如果您需要可移植性,您可以轻松地重载运算符以获取浮点数并在主机数据上对其进行不同的调用。)

我修改了您的示例以初始化数据并打印结果以验证它是否正确。

#include <stdio.h>
#include <stdlib.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/iterator/counting_iterator.h>

const int n = 32;
__constant__ float dev_x[n]; //the array in question

struct struct_max : public thrust::unary_function<float,float> {
float C;
struct_max(float _C) : C(_C) {}

// only works as a device function
__device__ float operator()(const int& i) const {
// use index into constant array
return fmax(dev_x[i],C);
}
};

void foo(const thrust::host_vector<float> &input_host_x, const float &x0) {
thrust::device_vector<float> dev_sol(n);
thrust::host_vector<float> host_sol(n);

thrust::device_ptr<float> dev_ptr = thrust::device_pointer_cast(dev_x);
thrust::transform(thrust::make_counting_iterator(0),
thrust::make_counting_iterator(n),
dev_sol.begin(),
struct_max(x0));
host_sol = dev_sol; //this line crashes

for (int i = 0; i < n; i++)
printf("%f\n", host_sol[i]);
}

int main() {
thrust::host_vector<float> x(n);

//magic happens populate x
for (int i = 0; i < n; i++) x[i] = rand() / (float)RAND_MAX;

cudaMemcpyToSymbol(dev_x,x.data(),n*sizeof(float));

foo(x, 0.5);
return(0);
}

关于cuda - 常量内存中的推力::device_vector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17064096/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com