2010-06-21 5 views
5

Désolé pour la question de sujet vague, mais je travaille sur des routines de traitement vidéo académique. Les algorithmes sont écrits dans MATLAB, et bien que ce soit bien pour le développement, il a traité une vidéo à environ 60spf, soit environ .0166fps. Inutile de dire que ce ne sera pas suffisant pour les démos et autres, alors mon travail d'été est de convertir la routine en quelque chose qui va courir considérablement plus vite.Quelle est la meilleure solution pour un problème parallèle embarrassant?

J'ai réécrit la partie la plus lente du code pour CUDA, la solution GPGPU de nvidia. Cependant, il y a aussi une grande partie du code qui semble être mieux fait sur le CPU, car il est relativement en série. Le problème est, la machine qui m'a été donnée a 2 processeurs Xeon, avec 8 cœurs logiques au total, et il semble dommage de goulot d'étranglement le code GPU en codant uniquement pour un seul core. Le processus de conversion vidéo est fonctionnel dans la mesure où chaque image ne dépend pas d'autres images, donc je pensais qu'une sorte de file d'attente/flux asynchrone serait la meilleure.

Voici ma question: quelle serait la meilleure façon de réaliser ce type de parallélisme avec le meilleur ratio d'effort pour accélérer le rendement?

Certaines des solutions que j'ai examinées sont OpenMP, .net TPL, et seulement pthreads simples. Je n'ai qu'une exposition de base à la programmation asynchrone, donc je préfère utiliser une bibliothèque ou quelque chose plutôt que de jouer avec des mutex et des barrières et me tirer plusieurs fois dans le pied. Cela ne me dérange pas d'apprendre, parce que c'est l'un de mes objectifs pour cet été, mais en même temps, le parallélisme est dur. Cependant, si la différence de vitesse est en fait très perceptible, je suis prêt à retirer mes cheveux pour quelques semaines. : P

Merci d'avance.

+0

Si vous pouvez décomposer le problème en plusieurs parties pouvant être traitées sans interférence (avec des points de synchronisation bien définis), alors la "bibliothèque" utilisée devrait être simplement du sucre ... un moyen simple est d'utiliser un pool de threads, files d'attente simultanées (une pour l'entrée, une pour la sortie), et seulement accéder aux objets/données que ce thread "possède" (ceci peut être agrandi à des structures externes immuables). –

Répondre

3

Si vous cherchez à maximiser vos efforts pour atteindre votre objectif, je vous recommande de regarder le TPL dans .NET. C'est probablement le moyen le plus simple de l'implémenter. En fonction de ce que fait votre code, vous pouvez soit former un pipeline ou simplement utiliser Parallel.For (ou ForEach) sur chaque "frame". Cela étant dit, si vous voulez vous en tenir au code natif non géré, une bonne option pourrait être le nouveau Parallel Patterns Library de Microsoft ou Intel's Threading Building Blocks. Ils ont tous deux des constructions similaires à la nouvelle TPL, en particulier pour le parallélisme des données, et rendraient cela assez facile à paralléliser, tant que "chaque image ne dépend pas d'autres images" reste vrai.

+0

Battez-moi! Ade Miller a eu une bonne conversation à TechEd sur les options de parallélisme disponibles avec .Net 4.0: http://www.msteched.com/2010/NorthAmerica/ARC205 – Mathias

+0

PPL ressemble à ce que je cherchais, merci. Une question cependant, utilise-t-elle du code managé comme C# ralentit sensiblement le mien, où c'est principalement de l'arithmétique en virgule flottante sur de grands tableaux? J'aime l'environnement de programmation beaucoup simplifié, mais avec des choses comme le traitement vidéo, je suis toujours hésitant à cause des craintes de la collecte des ordures et des frais généraux de vérification. Il s'agit peut-être d'une ancienne paranoïa de programmation C: \ – Xzhsh

+0

Xzhsh: Personnellement, j'utilise C# et le code managé pour le traitement des données scientifiques dans mon «job de jour». Ca se passe très bien, mais le perf. les caractéristiques sont différentes du code natif - vous devez donc adapter votre réflexion pour compenser. Personnellement, je ne m'inquiéterais pas du fait que le GC soit un problème, mais la vérification des limites d'un tableau peut vous ralentir (cela peut être désactivé). Cependant, dans la plupart des cas, un profilage soigneux et un «bon» code managé peuvent conduire à un code aussi rapide (et souvent plus rapide) que le code natif. –

1

Mon conseil serait d'aborder cette étape par étapes.

  1. Tout d'abord, prouvez que vous disposez d'une implémentation fonctionnelle autre que MATLAB. Ce n'est pas anodin et, franchement, je pense que vous devriez prévoir de dépenser 100% de vos cycles cérébraux avant de penser à la performance. Partitionnez votre solution: prouvez que vous pouvez prendre la routine que vous pensez découplée du reste de l'implémentation et l'isoler syntaxiquement du reste du code. Par exemple, si vous parliez d'un ray tracer, vous pourriez prendre les mathématiques qui résultent d'un seul point de vue tirant un rayon à travers un seul pixel dans l'environnement commun. Ceci est également non trivial car il vous faudra penser à ce qui est réellement commun (par exemple, la géométrie de l'environnement, les textures, etc.) et ce qui est spécifique à une situation unique (par exemple, rayon d'un oeil à un pixel) . Le profilage de performance est votre ami ici.

  2. Identifiez la syntaxe des bibliothèques ou des frameworks qui vous intéressent et qui seront nécessaires pour créer des threads/processus en parallèle, lancez-les et joignez leurs résultats après l'achèvement. Remarque: vous aurez besoin d'une exclusion mutuelle sur les données partagées, etc. Par exemple, dans le monde Java, ce sera java.util.concurrency. Essayez de créer deux (seulement deux) threads pour partitionner votre travail en deux. Ecrire des benchmarks qui vous permettent de mesurer votre solution initiale, la solution pour N = 2 threads et profiler l'enfer hors des résultats.

  3. Alors seulement devriez-vous même penser à une poursuite de la parallélisation.

Si vous suivez les étapes comme celles-ci, vous (a) réussir à votre tâche réelle (port de Matlab), (b) avoir quelque chose qui fonctionne à certaines mesures de performance connues et (c) avoir une vision claire aller de l'avant si vous souhaitez exploiter davantage les opportunités de parallélisation.

+0

Merci pour le conseil Bob! J'ai déjà porté les routines sur C, et le parallélisme ne serait que entre des trames complètement indépendantes. J'aime votre conseil, et je le garderai à l'esprit pour mon prochain projet – Xzhsh

+0

@Xzhsh, FYI, dans mon propre travail graphique, le meilleur parallélisme était en fait par image plutôt que d'assigner une image entière indépendamment aux processeurs individuels . L'environnement partagé a fortement motivé la partition des pixels vers les différents threads et accéléré le calcul d'une seule trame (c'était un raytracer après tout). Le choix des approches est probablement un autre bon sujet à étudier dans le cadre de votre projet. –

Questions connexes