2017-10-05 131 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