2012-12-26 4 views
1

Je vais écrire un programme OpenCL qui traite une énorme quantité de données au niveau de la tâche (aucun parallélisme n'est possible, mais la quantité de données est suffisamment élevée) Les données elles-mêmes sont lues à partir d'un fichier et le les résultats doivent être écrits dans un autre fichier. Maintenant, je pensais que ce serait peut-être le meilleur (le plus rapide) de laisser 1 thread lire le fichier et pousser les données vers les noyaux tandis qu'un autre thread récupère les données finies et les écrit dans un fichier. Donc, je voudrais réellement quelque chose comme ReadData-> CopyToDevice-> ExecuteKernel-> CopyToHost-> WriteDataStreaming dans OpenCL

Y at-il un exemple, comment faire le mieux? Je commencerais avec un tableau de 10 (files d'attente, InputMemory, OutputMemory, Events). Premier thread: Lire les données, attendre que l'entrée d'événement suivant soit nulle, remplir ce tableau,
2ème thread: événement! = Null-> waitforevent, écrire des données, définir l'événement à null Ou peut-être utiliser un 10-Semaphore au lieu de vérifier null

Répondre

0

Je fais quelque chose similar pour le traitement d'image mais avant de penser à faire quoi que ce soit, vous devriez réellement profiler pour voir où sont les goulots d'étranglement. Je ne sais pas à quel point vos noyaux sont intensifs en calcul, mais vous ne devriez pas sous-estimer les E/S. Tout d'abord: oui, utiliser trois threads au total est probablement une bonne idée pour masquer les latences d'E/S. Mais dix files d'attente de commandes est beaucoup trop, un pour chaque GPU est plus que suffisant. De plus, si vous n'avez qu'un seul GPU, il est inutile de lui fournir dix tampons différents, s'il est seulement capable d'en traiter un. Donc, vous êtes mieux avec une stratégie de double tampon et de bloquer les lectures et les écritures.

+0

Le noyau traite lui-même les données de taille fixe et de sortie de taille variable. Un processeur peut faire environ 10k de jeux de données par seconde (~ 150B chacun) J'ai donc pensé à donner au noyau environ 10k ensembles de données répartis sur 31 WorkItems par groupe (31 en raison de la mémoire locale requise) et quelques groupes. – Flamefire

+0

J'ai donc pensé que pendant que je transférais des données au noyau, je pouvais faire le calcul dans le noyau pour les ensembles de données précédents et lire les données du disque pour les prochains jeux de données. Ce serait donc comme un pipeline avec 4 étapes: Lire à partir du disque, écrire sur le périphérique, traiter les données/lire depuis le périphérique, écrire sur le disque. Il y a un exemple de calcul dans une file d'attente pendant que l'autre file est en train de transférer des données et inversement. Donc, le même noyau est instancié 2 fois et appelé ainsi 2 files d'attente. Les noyaux pourraient même courir en même temps, étant donné que les CU ne le peuvent pas? – Flamefire

+0

Il n'y a aucune garantie que les transferts et les exécutions sont programmés en mode non-bloquant sauf pour la commande. Vous pouvez donc utiliser la même file d'attente pour le transfert et l'exécution. Une file d'attente est simplement une abstraction de l'envoi des informations GPU (soit l'exécution du noyau, soit les données). Mais pourquoi ne pas essayer? – matthias

0

Utilisez également des files d'attente de commandes OpenCL distinctes pour le téléchargement, le traitement et le téléchargement, avec clEvents pour créer des dépendances entre elles. Cela permettra au matériel de chevaucher ces opérations lorsque la prise en charge GPU