2017-10-05 3 views
3

Si j'ai deux tableaux ED cudaMalloc, je peux les échanger sans mouvements de mémoire en inversant simplement les pointeurs associés.Permutation de vecteurs périphériques Thrust CUDA sans mouvements de mémoire

Si j'ai deux CUDA Thrust device_vectors, dire d_a et d_b, je peux les échanger à l'aide d'un troisième vecteur de temorary, dire d_c, mais cela nécessitera des mouvements de mémoire.

Ma question est la suivante: existe-t-il un moyen d'échanger CUDA Thrust device_vectors sans mouvements de mémoire?

+1

La classe 'poussée :: vECTOR' a un membre de type' contiguous_storage' qui est utilisé pour stocker le contenu du vecteur. Lorsque les vecteurs sont échangés, en interne, seul l'itérateur 'begin()', 'size' et' allocator' de 'contiguous_storage' sont permutés. Il n'y a donc pas de copie de mémoire des données impliquées. Vous pouvez le vérifier dans la fonction membre ['swap'] (https://github.com/thrust/thrust/blob/master/thrust/detail/contiguous_storage.inl#L181) du fichier' contiguous_storage.inl'. – sgarizvi

+1

Dans le cas d'un opérateur d'affectation, si vous regardez le code de ['vector_base :: operator ='] (https://github.com/thrust/thrust/blob/master/thrust/detail/vector_base.inl#L89), il utilise la fonction 'assign' qui semble effectuer une copie mémoire complète du contenu vectoriel. – sgarizvi

+0

@sgarizvi Merci pour vos commentaires.En fait, c'est la même objection @talonmies a souligné dans ses commentaires ci-dessous. Cependant, la chose étrange est que je ne peux pas trouver des copies de mémoire dans le calendrier. Peut-être que "thrust" utilise un noyau pour effectuer la copie? – JackOLantern

Répondre

3

Pas que je sache.

Il n'y a aucun constructeur exposé qui prenne un device_ptr existant, et le vecteur de base sous-jacent dans device_vector est privé, donc il n'y a aucun moyen de plonger dedans et d'exécuter l'échange de pointeur vous-même. Ce sont les seuls moyens que je puisse imaginer pour que cela fonctionne sans déclencher le constructeur de copie standard.


Modifier pour ajouter qu'il semble que cette réponse est erronée. Il semble que les changements récents (probablement autour de la poussée 1.6) ont mis en œuvre un mécanisme interne d'échange d'échange de pointeurs qui peut être appelé via device_vector.swap(). Cela contourne l'idiome habituel de constructeur de copie pour swap() et ne déclenchera pas les transferts de mémoire .

+0

Si vous n'êtes pas au courant, alors il est 99.99% probable que ce n'est pas possible :-) Merci, comme toujours. – JackOLantern

+0

En pensant à cela, vous pourriez être capable de faire des choses en piratant une classe allocator personnalisée qui retourne la mémoire d'un autre vecteur de périphérique. Mais alors vous avez beaucoup d'autres problèmes qui ne peuvent probablement pas être résolus – talonmies

+0

Juste une question: est-ce que 'd_b.swap (d_a)' implique des mouvements de mémoire? – JackOLantern

2

Il semble que device_vector.swap() évite les mouvements de la mémoire.

En effet, considérons le code suivant:

#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; 
} 

utilisant

d_b.swap(d_a); 

Si nous vous présentons, nous ne voyons pas le mouvement de mémoire de l'appareil à appareil dans la chronologie:

enter image description here

Si, de l'autre côté, nous changeons d_b.swap(d_a) à

d_b = d_a; 

mouvements incontrôlés de dispositif à dispositif apparaissent dans la ligne de temps:

enter image description here

Enfin, le moment est nettement en faveur de d_b.swap(d_a), plutôt que d_b = d_a. Pour N = 33554432, le moment est

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