thrust::sort_by_key对zip_iterator值排序失效及相关问题求助
Thrust库关键用法答疑
1. 用设备原始指针正确声明zip_iterator
要基于设备原始指针创建zip_iterator,核心是明确设备空间的迭代器类型,推荐用thrust::device_ptr包装原始指针后组合:
// 假设b_dev、c_dev是通过cudaMalloc分配的设备原始指针 auto b_device_ptr = thrust::device_ptr<int>(b_dev); auto c_device_ptr = thrust::device_ptr<int>(c_dev); // 用make_tuple组合多个设备指针,再生成zip_iterator auto zip_iterator = thrust::make_zip_iterator(thrust::make_tuple(b_device_ptr, c_device_ptr));
如果直接使用原始设备指针,Thrust也能识别,但device_ptr能明确标注空间,避免主机/设备空间混淆导致的错误。
2. 实现zip_iterator的同步排序
仅键排序正确但值未同步,大概率是空间不匹配或未指定执行策略导致的。正确步骤:
- 确保键数组和zip_iterator指向的数组都在同一设备空间(或同一主机空间);
- 调用
thrust::sort_by_key时显式指定执行策略(如thrust::device),避免Thrust自动推导错误; - 排序完成后,若要查看结果,需将设备端数组拷贝回主机(不能直接访问设备原始指针)。
示例代码:
const int n = 5; int a_host[] = {3,1,4,2,5}; int b_host[] = {30,10,40,20,50}; int c_host[] = {300,100,400,200,500}; // 分配设备内存并拷贝数据 int *a_dev, *b_dev, *c_dev; cudaMalloc(&a_dev, n*sizeof(int)); cudaMalloc(&b_dev, n*sizeof(int)); cudaMalloc(&c_dev, n*sizeof(int)); cudaMemcpy(a_dev, a_host, n*sizeof(int), cudaMemcpyHostToDevice); cudaMemcpy(b_dev, b_host, n*sizeof(int), cudaMemcpyHostToDevice); cudaMemcpy(c_dev, c_host, n*sizeof(int), cudaMemcpyHostToDevice); // 创建zip_iterator auto zip_it = thrust::make_zip_iterator(thrust::make_tuple(thrust::device_ptr<int>(b_dev), thrust::device_ptr<int>(c_dev))); // 显式指定设备执行策略,同步排序键与zip值 thrust::sort_by_key(thrust::device, a_dev, a_dev + n, zip_it); // 拷贝回主机查看结果 cudaMemcpy(b_host, b_dev, n*sizeof(int), cudaMemcpyDeviceToHost); cudaMemcpy(c_host, c_dev, n*sizeof(int), cudaMemcpyDeviceToHost);
3. 正确使用带自定义算子的thrust::reduce_by_key
编译失败通常是因为算子修饰符缺失、类型不匹配或未指定执行策略,需注意以下几点:
- 自定义算子需添加
__host__ __device__修饰,确保能在主机/设备端执行; - 算子的参数、返回值类型要与输入值的类型匹配;
- 显式指定执行策略,同时确保所有迭代器处于同一空间;
- 若使用原始指针,建议用
thrust::device_ptr包装。
示例代码(自定义求和合并算子):
// 自定义合并算子:对两个int值求和 struct SumOperator { __host__ __device__ int operator()(const int& lhs, const int& rhs) const { return lhs + rhs; } }; int main() { const int n = 6; int keys_host[] = {1,1,2,2,3,3}; int values_host[] = {10,20,30,40,50,60}; // 设备端分配与拷贝 thrust::device_vector<int> keys_dev(keys_host, keys_host + n); thrust::device_vector<int> values_dev(values_host, values_host + n); thrust::device_vector<int> output_keys, output_values; // 带自定义算子的reduce_by_key thrust::reduce_by_key(thrust::device, keys_dev.begin(), keys_dev.end(), values_dev.begin(), std::back_inserter(output_keys), std::back_inserter(output_values), thrust::equal_to<int>(), // 键相等判断算子(可自定义) SumOperator()); // 自定义合并算子 // 输出结果 for(size_t i=0; i<output_keys.size(); i++){ printf("Key: %d, Sum: %d\n", output_keys[i], output_values[i]); } return 0; }
内容的提问来源于stack exchange,提问作者AzuxirenLeadGuy
相关产品推荐
相关产品推荐

