2017-10-05 96 views
3

如果我有两个cudaMalloc ed数组,我可以通过交换相关指针来交换它们而无需记忆移动。交换CUDA无记忆移动的推力设备向量

如果我有两个CUDA推力device_vectors,说d_ad_b,我可以通过使用第三temorary向量交换他们,说d_c,但这将需要记忆的动作。

我的问题是:有没有办法将CUDA Thrust device_vectors交换为无内存移动?

+1

的'推力:: VECTOR'类具有用于存储所述矢量内容类型'contiguous_storage'的成员。当矢量交换时,内部只交换'contiguous_storage'的'begin()'迭代器,'size'和'allocator'。所以没有涉及数据的内存拷贝。你可以在文件'contiguous_storage.inl'内的['swap'](https://github.com/thrust/thrust/blob/master/ thr/modules/contact.inl#L181)成员函数中检查它。 – sgarizvi

+1

在赋值运算符的情况下,如果查看['vector_base :: operator =']的代码(https://github.com/thrust/thrust/blob/master/thrust/detail/vector_base.inl#L89 ),它使用似乎执行矢量内容的完整存储器复制的'assign'函数。 – sgarizvi

+0

@sgarizvi感谢您的意见。其实,这是@talonmies在他的评论中指出的同样的反对意见。然而,奇怪的是我无法在时间轴中找到内存拷贝。也许'thrust'使用内核来执行复制? – JackOLantern

回答

3

不是我所知道的。

没有公开的构造函数需要现有的device_ptr,并且device_vector中的底层基向量是私有的,所以无法潜入并自己执行指针交换。这些将是我能想到的唯一方法,使其在不触发标准拷贝构造函数的情况下进行这项工作。


编辑补充说它看起来这个答案是错误的。看来最近(可能在推力1.6左右)的变化已经实现了一个内部指针交换交换机制,可以通过device_vector.swap()调用。这绕开了通常的swap()的复制构造函数成语,并且不会触发内存传输 。

+0

如果您不知道,那么99.99%可能是不可能的:-)谢谢,一如既往。 – JackOLantern

+0

想一想,你可以通过黑客自定义的分配器类来执行操作,该类会返回另一个设备向量的内存。但是,你有很多其他问题可能无法解决 – talonmies

+0

只是一个问题:'d_b.swap(d_a)'暗示内存移动? – JackOLantern

2

看起来device_vector.swap()可以避免内存移动。使用

d_b.swap(d_a); 

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 

#include <stdio.h> 

#include <thrust\device_vector.h> 

void printDeviceVector(thrust::device_vector<int> &d_a) { 

    for (int k = 0; k < d_a.size(); k++) { 

     int temp = d_a[k]; 
     printf("%i\n", temp); 

    } 

} 

int main() 
{ 
    const int N = 10; 

    thrust::device_vector<int> d_a(N, 1); 
    thrust::device_vector<int> d_b(N, 2); 

    // --- Original 
    printf("Original device vector d_a\n"); 
    printDeviceVector(d_a); 
    printf("Original device vector d_b\n"); 
    printDeviceVector(d_b); 

    d_b.swap(d_a); 

    // --- Original 
    printf("Final device vector d_a\n"); 
    printDeviceVector(d_a); 
    printf("Final device vector d_b\n"); 
    printDeviceVector(d_b); 

    d_a.clear(); 
    thrust::device_vector<int>().swap(d_a); 
    d_b.clear(); 
    thrust::device_vector<int>().swap(d_b); 

    cudaDeviceReset(); 

    return 0; 
} 

如果我们描述文件时,我们看到在时间轴上没有设备到设备内存运动:

事实上,考虑下面的代码

enter image description here

如果在另一方面我们更改d_b.swap(d_a)

d_b = d_a; 

然后设备到设备的运动出现在时间轴:

enter image description here

最后,定时是显著赞成d_b.swap(d_a),而不是d_b = d_a。对于N = 33554432,定时是

d_b.swap(d_a)  0.001152ms 
d_b = d_a   3.181824ms