web-dev-qa-db-fra.com

Programmation GPU de haut niveau en C ++

J'ai étudié les bibliothèques/extensions pour C++ qui permettront un traitement basé sur GPU à un niveau élevé. Je ne suis pas un expert en programmation GPU et je ne veux pas creuser trop profondément. J'ai un réseau neuronal composé de classes avec des fonctions virtuelles. J'ai besoin d'une bibliothèque qui fait essentiellement l'allocation de GPU pour moi - à un niveau élevé. Il y a un gars qui a écrit une thèse sur un système appelé GPU ++ qui fait la plupart des trucs GPU pour vous. Je ne trouve le code nulle part, juste sa thèse.

Est-ce que quelqu'un connaît une bibliothèque similaire ou quelqu'un a-t-il le code pour GPU ++? Les bibliothèques comme CUDA sont de niveau trop bas et ne peuvent pas gérer la plupart de mes opérations (du moins pas sans réécrire tous mes processus et algorithmes - ce que je ne veux pas faire).

33
goocreations

La bibliothèque Thrust fournit des conteneurs, des primitives parallèles et des algorithmes. Toutes ces fonctionnalités sont bien intégrées dans une syntaxe de type STL. Donc, si vous êtes familier avec STL, vous pouvez réellement écrire des programmes CUDA entiers en utilisant uniquement Thrust, sans avoir à écrire un seul noyau CUDA. Jetez un œil aux exemples simples dans le Guide de démarrage rapide pour voir le type de programmes de haut niveau que vous pouvez écrire en utilisant Poussée.

28
Ashwin Nanjappa

Il existe de nombreuses bibliothèques de haut niveau dédiées à la programmation GPGPU. Puisqu'ils s'appuient sur CUDA et/ou OpenCL, ils doivent être choisis judicieusement (un programme basé sur CUDA ne fonctionnera pas sur les GPU d'AMD, sauf s'il passe par une étape de prétraitement avec des projets tels que gpuocelot ).

CUDA

Vous pouvez trouver quelques exemples de bibliothèques CUDA sur NVIDIA site Web .

  • Poussée : la description officielle parle d'elle-même

Thrust est une bibliothèque d'algorithmes parallèles qui ressemble à la bibliothèque de modèles standard C++ (STL). L'interface de haut niveau de Thrust améliore considérablement la productivité du programmateur tout en permettant la portabilité des performances entre les GPU et les processeurs multicœurs. L'interopérabilité avec les technologies établies (telles que CUDA, TBB et OpenMP) facilite l'intégration avec les logiciels existants.

Comme @ Ashwin l'a souligné, la syntaxe STL de Thrust en fait une bibliothèque largement choisie lors du développement de programmes CUDA. Un rapide coup d'œil aux exemples montre le type de code que vous écrirez si vous décidez d'utiliser cette bibliothèque. Le site Web de NVIDIA présente les fonctionnalités clés de cette bibliothèque. Un présentation vidéo (de GTC 2012) est également disponible.

CUB fournit des composants logiciels de pointe et réutilisables pour chaque couche du mode de programmation CUDA. Il s'agit d'une bibliothèque flexible de primitives de blocs de threads coopératifs et d'autres utilitaires pour la programmation du noyau CUDA.

Il fournit des primitives parallèles à l'échelle du périphérique, du bloc et de la chaîne telles que le tri parallèle, le balayage des préfixes, la réduction, l'histogramme, etc.

Il est open-source et disponible sur GitHub . Il n'est pas de haut niveau du point de vue de l'implémentation (que vous développez dans les noyaux CUDA), mais fournit des algorithmes et des routines de haut niveau.

  • mshadow : bibliothèque légère de modèles CPU/matrice GPU/tensor en C++/CUDA.

Cette bibliothèque est principalement utilisée pour l'apprentissage automatique et s'appuie sur modèles d'expression .

À partir d'Eigen 3.3, il est désormais possible d'utiliser les objets et algorithmes d'Eigen dans les noyaux CUDA. Cependant, seul un sous-ensemble de fonctionnalités est pris en charge pour garantir qu'aucune allocation dynamique n'est déclenchée dans un noyau CUDA.

OpenCL

Notez que OpenCL fait plus que l'informatique GPGPU, car il prend en charge des plates-formes hétérogènes (processeurs multicœurs, GPU, etc.).

  • OpenACC : ce projet fournit un support de type OpenMP pour GPGPU. Une grande partie de la programmation est effectuée implicitement par le compilateur et l'API d'exécution. Vous pouvez trouver un exemple de code sur leur site Web.

L'interface du programme d'application OpenACC décrit une collection de directives du compilateur pour spécifier les boucles et les régions de code en C, C++ et Fortran standard à décharger d'un CPU hôte vers un accélérateur attaché, offrant une portabilité entre les systèmes d'exploitation, les CPU hôtes et les accélérateurs.

  • Bolt : bibliothèque open source avec interface de type STL.

Bolt est une bibliothèque de modèles C++ optimisée pour l'informatique hétérogène. Bolt est conçu pour fournir des implémentations de bibliothèque hautes performances pour des algorithmes courants tels que l'analyse, la réduction, la transformation et le tri. L'interface Bolt a été modélisée sur la bibliothèque de modèles standard C++ (STL). Les développeurs familiarisés avec la STL reconnaîtront de nombreuses API Bolt et techniques de personnalisation.

  • Boost.Compute : comme @ Kyle Lutz dit, Boost.Compute fournit un style STL interface pour OpenCL. Notez que ce n'est pas (encore) une bibliothèque Boost officielle.

  • SkelCL "est une bibliothèque fournissant des abstractions de haut niveau pour une programmation allégée de systèmes hétérogènes parallèles modernes". Cette bibliothèque s'appuie sur programmation squelette , et vous pouvez trouver plus d'informations dans leur documents de recherche .

CUDA + OpenCL

  • ArrayFire est une bibliothèque de programmation GPGPU open-source (autrefois propriétaire). Ils ont d'abord ciblé CUDA, mais prennent désormais également en charge OpenCL. Vous pouvez vérifier les exemples disponibles en ligne. Le site Web de NVIDIA fournit un bon résumé de ses principales fonctionnalités.

Information complémentaire

Bien que cela ne soit pas vraiment dans le cadre de cette question, il existe également le même type de support pour les autres langages de programmation:

Si vous devez faire de l'algèbre linéaire (par exemple) ou d'autres opérations spécifiques, des bibliothèques mathématiques dédiées sont également disponibles pour CUDA et OpenCL (par exemple ViennaCL , [~ # ~] cublas [~ # ~] , [~ # ~] magma [~ # ~] etc.).

Notez également que l'utilisation de ces bibliothèques ne vous empêche pas d'effectuer des opérations de bas niveau si vous devez effectuer un calcul très spécifique.

Enfin, nous pouvons mentionner l'avenir de la bibliothèque standard C++. Il y a eu un travail considérable pour ajouter le support du parallélisme. C'est toujours une spécification technique , et les GPU ne sont pas explicitement mentionnés AFAIK (bien que Jared Hoberock de NVIDIA, développeur de Thrust, soit directement impliqué), mais la volonté d'en faire une réalité est définitivement là.

47
BenC

Jetez un oeil à Boost.Compute . Il fournit une interface de type STL de haut niveau comprenant des conteneurs comme vector<T> et des algorithmes comme transform() et sort() .

Il est construit sur OpenCL lui permettant de fonctionner sur la plupart des GPU et CPU modernes, y compris ceux de NVIDIA, AMD et Intel.

15
Kyle Lutz

Une autre bibliothèque de haut niveau est VexCL - une bibliothèque de modèles d'expression vectorielle pour OpenCL. Il fournit une notation intuitive pour les opérations vectorielles et est disponible sous la licence MIT.

2
ddemidov

Si vous recherchez des conteneurs de dimensions supérieures et la capacité de passer et de manipuler ces conteneurs en code noyau, j'ai passé les dernières années à développer l'API ecuda pour m'aider dans mes propres projets de recherche scientifique. (il a donc été mis à l'épreuve). Espérons que cela puisse combler une niche nécessaire. Un bref exemple de la façon dont il peut être utilisé (les fonctionnalités C++ 11 sont utilisées ici, mais ecuda fonctionnera bien avec les compilateurs pré-C++ 11):

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <vector>

#include <ecuda/ecuda.hpp>

// kernel function
__global__
void calcColumnSums(
  typename ecuda::matrix<double>::const_kernel_argument mat,
  typename ecuda::vector<double>::kernel_argument vec
)
{
    const std::size_t t = threadIdx.x;
    auto col = mat.get_column(t);
    vec[t] = ecuda::accumulate( col.begin(), col.end(), static_cast<double>(0) );
}

int main( int argc, char* argv[] )
{

    // allocate 1000x1000 hardware-aligned device memory matrix
    ecuda::matrix<double> deviceMatrix( 1000, 1000 );

    // generate random values row-by-row and copy to matrix
    std::vector<double> hostRow( 1000 );
    for( std::size_t i = 0; i < 1000; ++i ) {
        for( double& x : hostRow ) x = static_cast<double>(Rand())/static_cast<double>(Rand_MAX);
        ecuda::copy( hostRow.begin(), hostRow.end(), deviceMatrix[i].begin() );
    }

    // allocate device memory for column sums
    ecuda::vector<double> deviceSums( 1000 );

    CUDA_CALL_KERNEL_AND_WAIT(
        calcColumnSums<<<1,1000>>>( deviceMatrix, deviceSums )
    );

    // copy columns sums to Host and print
    std::vector<double> hostSums( 1000 );
    ecuda::copy( deviceSums.begin(), deviceSums.end(), hostSums.begin() );

    std::cout << "SUMS =";
    for( const double& x : hostSums ) std::cout << " " << std::fixed << x;
    std::cout << std::endl;

    return 0;

}

Je l'ai écrit pour être aussi intuitif que possible (généralement aussi simple que de remplacer std :: par ecuda: :). Si vous connaissez STL, alors ecuda devrait faire ce que vous attendez logiquement d'une extension C++ basée sur CUDA.

2
scottzed

Le projet cpp-opencl fournit un moyen de faciliter la programmation des GPU pour le développeur. Il vous permet d'implémenter le parallélisme de données sur un GPU directement en C++ au lieu d'utiliser OpenCL.

Veuillez voir http://dimitri-christodoulou.blogspot.com/2014/02/implement-data-parallelism-on-gpu.html

Et le code source: https://github.com/dimitrs/cpp-opencl

Voir l'exemple ci-dessous. Le code de la fonction lambda parallel_for_each est exécuté sur le GPU, et tout le reste est exécuté sur le CPU. Plus précisément, la fonction "square" est exécutée à la fois sur le CPU (via un appel à std :: transform) et sur le GPU (via un appel à compute :: parallel_for_each).

#include <vector>
#include <stdio.h>
#include "ParallelForEach.h"

template<class T> 
T square(T x)  
{
    return x * x;
}

void func() {
  std::vector<int> In {1,2,3,4,5,6};
  std::vector<int> OutGpu(6);
  std::vector<int> OutCpu(6);

  compute::parallel_for_each(In.begin(), In.end(), OutGpu.begin(), [](int x){
      return square(x);
  });


  std::transform(In.begin(), In.end(), OutCpu.begin(), [](int x) {
    return square(x);
  });

  // 
  // Do something with OutCpu and OutGpu …..........

  //

}

int main() {
  func();
  return 0;
}
1
Dimitri

La nouvelle OpenMP version 4 inclut désormais la prise en charge du déchargement d'accélérateur.

Les GPU AFAIK sont considérés comme des accélérateurs.

1
Pietro

C++ AMP est la réponse que vous recherchez.

0
isti_spl