2017-10-05 14 views
3

두 개의 cudaMalloc 어레이가있는 경우 관련 포인터를 바꾸기 만하면 메모리 이동없이 스왑 할 수 있습니다. 나는 두 개의 CUDA 스러스트 device_vectors이있는 경우메모리 이동이없는 CUDA 추력 장치 벡터 교환

는, 나는 제 3 temorary 벡터를 사용하여 그것들을 교체 할 수 있습니다, d_ad_bd_c 말을하지만,이 메모리 움직임을 필요로 할 것이다.

제 질문은 메모리 이동없이 CUDA Thrust device_vectors를 바꾸는 방법이 있습니까?

+1

은'추력 :: vector' 클래스는 벡터의 내용을 저장하는 데 사용되는 유형 'contiguous_storage'의 부재를 가진다. 벡터가 바뀌면, 내부적으로'begin()'반복자,'contiguous_storage'의'size'와'allocator' 만 바뀝니다. 따라서 관련된 데이터의 메모리 복사본이 없습니다. 이 파일은 'contiguous_storage.inl' 파일의 [swap'] (https://github.com/thrust/thrust/blob/master/thrust/detail/contiguous_storage.inl#L181) 멤버 함수에서 확인할 수 있습니다. – sgarizvi

+1

대입 연산자의 경우, ['vector_base :: operator ='] (https://github.com/thrust/thrust/blob/master/thrust/detail/vector_base.inl#L89) 코드를 보면,), 벡터 내용의 완전한 메모리 복사본을 수행하는 것처럼 보이는'assign' 함수를 사용합니다. – sgarizvi

+0

@sgarizvi 의견을 보내 주셔서 감사합니다.사실, 이것은 아래의 그의 의견에서 지적한 것과 동일한 반대입니다. 그러나 이상한 것은 타임 라인에서 메모리 복사본을 찾을 수 없다는 것입니다. 아마도'추력'은 카피를하기 위해 커널을 사용 했을까? – 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 = d_a보다 d_b.swap(d_a)에 찬성 크게이다. N = 33554432 들어, 타이밍

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