2015-09-14 2 views
1

Je me demandais quel est le moyen le plus rapide de calculer un produit matriciel-vectoriel clairsemé y = Ax dans CUDA sur plusieurs GPU (disons n).Produit vectoriel Sparse Matrix sur plusieurs GPUs

Mon approche naïve serait de diviser le vecteur x et y en n morceaux, 1 morceau sur chaque GPU. Puis aussi diviser la matrice A dans les petites n^2 blocs A_ij et calcul

y_i = \sum_j A_{i,j} x_j, // GPU j stores A_{i,j} and x_j, result is copied 
          // to and summed up on GPU i 

sur les différents processeurs graphiques j = 1..n avec disons cuSPARSE. Cela fonctionnerait-il? Avec l'architecture de mémoire unifiée, tous les GPU devraient en principe pouvoir accéder à la mémoire globale.

Le transfert de mémoire entre les GPU va-t-il être incroyablement lent? Je ne m'attends pas à une grande accélération, mais je me demandais si cela allait être plus lent que de faire la multiplication matricielle-vectorielle sur un seul GPU.

+1

Je ne pense pas qu'il y ait une réponse générale à cette question, elle est loin d'être large. Il y a eu un * lot * de recherches sur le produit vectoriel à matrice clairsemée pour les systèmes à mémoire distribuée, y compris les GPU. Vous feriez mieux de lire certaines de ces questions que de poser une question comme celle-ci ici [SO] – talonmies

+0

Vous avez raison. Je suppose que ce que je cherchais est une implémentation simple/bon marché (réutilisant les appels à cuSPARSE) qui fonctionne correctement sur plusieurs GPU. – yon

Répondre

2

Je suggérerais une approche différente. Ne pas casser le vecteur x en morceaux. Transférer x vers tous les GPU.

Décomposer la matrice A en fonction des rangées. Ainsi, par exemple, si A avait 9 lignes, et vous avez 3 GPUs, alors transférez les lignes 1-3 de A au premier GPU, 4-6 de A au deuxième GPU, et 7-9 de A au troisième GPU .

Ensuite, les 3 Calculons pièces individuelles de y sur les 3 processeurs graphiques:

y[1-3] = A[1-3]*x 
y[4-6] = A[4-6]*x 
y[7-9] = A[7-9]*x 

pourrait être fait Chacune de ces 3 opérations avec cusparse<T>csrmv, par exemple (ou CUB a maintenant une routine spmv aussi).

Le réassemblage du vecteur y devrait être trivial (concaténation). Il n'y a pas besoin de transfert de données inter-GPU au cours du calcul, uniquement lors du transfert des résultats (y).

Une "optimisation" possible serait de partitionner A basé sur "travail" plutôt que naïvement par des lignes. Mais le bénéfice de cela dépendrait de la structure de A, ce qui nécessiterait une analyse. Une approche simpliste de cette optimisation pourrait consister à simplement diviser A en fonction de l'égalisation (approximative) du nombre d'éléments NZ dans chaque segment.

+1

Une décomposition de graphique pour distribuer la matrice serait une autre approche standard que j'aurais pensé. – talonmies