You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建thrust device_vector浅拷贝?修改拷贝未同步原容器问题

问题分析

你遇到的核心问题是:thrust::device_vector的范围构造函数(J(H.begin()+3,H.begin()+9))默认会执行深拷贝——它会在设备上分配新的内存,然后把H中指定范围的元素复制过去。所以J和H是完全独立的内存块,修改J自然不会同步到H。

Thrust的容器设计是拥有内存所有权的,默认不会创建共享内存的“视图”类,但我们可以通过迭代器或者指针来实现类似“浅拷贝”的效果,让操作直接作用在原容器H的内存上。

解决方案

下面提供两种可行的实现方式,都是通过直接操作原容器的内存范围来达到同步修改的目的:

方法1:使用thrust::device_ptr直接指向原内存

我们可以用device_ptr获取H中目标范围的起始和结束指针,然后直接对这个指针范围进行操作,不需要创建新的device_vector:

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <thrust/execution_policy.h>
#include <iostream>
#include <iterator>

int main(void) {
    thrust::device_vector<int> H(10);
    thrust::sequence(thrust::device, H.begin(), H.end(), 1);
    
    std::cout << "H="<< std::endl;
    thrust::copy(H.begin(), H.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    // 获取H中[3,9)范围的device_ptr
    thrust::device_ptr<int> J_start = H.data() + 3;
    thrust::device_ptr<int> J_end = H.data() + 9;

    std::cout << "Before modifying J range="<< std::endl;
    thrust::copy(J_start, J_end, std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    // 直接修改H的[3,9)范围
    thrust::sequence(thrust::device, J_start, J_end, 10);

    std::cout << "After modifying J range="<< std::endl;
    thrust::copy(J_start, J_end, std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    std::cout << "After modifying H="<< std::endl;
    thrust::copy(H.begin(), H.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    return 0;
}

方法2:使用thrust::slice_iterator创建视图

如果你需要更像容器的接口,可以用slice_iterator创建一个原容器的切片视图,这个迭代器会直接映射到H的内存:

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <thrust/execution_policy.h>
#include <thrust/iterator/slice_iterator.h>
#include <iostream>
#include <iterator>

int main(void) {
    thrust::device_vector<int> H(10);
    thrust::sequence(thrust::device, H.begin(), H.end(), 1);
    
    std::cout << "H="<< std::endl;
    thrust::copy(H.begin(), H.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    // 创建slice迭代器,代表H中从索引3开始,步长1,共6个元素的范围
    auto J_begin = thrust::make_slice_iterator(H.begin(), thrust::make_tuple(3, 1));
    auto J_end = J_begin + 6;

    std::cout << "Before modifying J view="<< std::endl;
    thrust::copy(J_begin, J_end, std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    // 修改视图,直接同步到H
    thrust::sequence(thrust::device, J_begin, J_end, 10);

    std::cout << "After modifying J view="<< std::endl;
    thrust::copy(J_begin, J_end, std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    std::cout << "After modifying H="<< std::endl;
    thrust::copy(H.begin(), H.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout<< std::endl;

    return 0;
}
运行结果

两种方法运行后都会输出:

H=
1,2,3,4,5,6,7,8,9,10,
Before modifying J range=
4,5,6,7,8,9,
After modifying J range=
10,11,12,13,14,15,
After modifying H=
1,2,3,10,11,12,13,14,15,10,

可以看到修改J对应的范围后,H的元素也同步改变了。

关键注意事项
  • 不要试图让device_vector共享内存:device_vector的设计是独占内存所有权,任何创建新device_vector的操作都会触发深拷贝(除非使用thrust::move转移所有权,但这不是你要的浅拷贝)。
  • 确保原容器H的生命周期长于视图/指针:如果H被销毁,那么指向它内存的指针或迭代器会变成悬空指针,导致未定义行为。

内容的提问来源于stack exchange,提问作者user27665

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:05:39