2010-07-07 4 views
3

Voici ce que je fais:Meilleure façon de copier plusieurs vecteurs std :: en 1? (Multithreading)

Je prends des points de Bézier et en cours d'exécution interpolation Bézier puis stocker le résultat dans un std::vector<std::vector<POINT>.

Le calcul de Bézier a été me ralentir en est ainsi ce J'ai fait.

Je commence par un std::vector<USERPOINT> qui est une structure avec un point et 2 autres points pour les poignées bezier.

Je les divise en ~ 4 groupes et assigner chaque fil à faire 1/4 du travail. Pour ce faire, j'ai créé 4 std::vector<std::vector<POINT> > pour stocker les résultats de chaque thread.A la fin, tous les points doivent être en 1 vecteur continu, avant d'utiliser le multithreading j'ai accédé directement à ceci, mais maintenant je réserve la taille des 4 vecteurs produits par le threads et les insérer dans le vecteur d'origine, dans le bon ordre. Cela fonctionne, mais malheureusement la partie de copie est très lente et la rend plus lente que sans multithreading. Alors maintenant, mon nouveau goulot d'étranglement copie les résultats au vecteur. Comment pourrais-je faire de cette façon plus efficacement?

Merci

Répondre

4

Tous les threads ont mis leurs résultats dans un seul vecteur contigu comme avant. Vous devez vous assurer que chaque thread accède uniquement aux parties du vecteur qui sont séparées des autres. Tant que c'est le cas (ce qui devrait être le cas - vous ne voulez pas générer deux fois la même sortie), chacun fonctionne avec une mémoire distincte des autres, et vous n'avez pas besoin de verrouillage (etc.) pour que les choses fonctionnent. Vous devez toutefois vous assurer que le vecteur pour le résultat a la taille correcte pour tous les résultats en premier - plusieurs threads essayant (par exemple) d'appeler resize() ou push_back() sur le vecteur va faire des ravages dans l'urgence (sans parler de provoquer la copie, que vous voulez clairement éviter ici). Edit: Comme Billy O'Neal l'a souligné, la manière habituelle de faire ceci est de passer un pointeur sur chaque partie du vecteur où chaque thread déposera sa sortie. Par souci d'argument, supposons que nous utilisons le std::vector<std::vector<POINT> > mentionné comme la version originale des choses. Pour le moment, je vais passer sur les détails de la création des threads (d'autant plus que cela varie d'un système à l'autre). Pour simplifier, je suppose également que le nombre de courbes à générer est un multiple exact du nombre de threads - en réalité, les courbes ne se diviseront pas exactement de la même manière, donc vous devrez "fudge" le compte pour un thread, mais ce n'est vraiment pas lié à la question à portée de main.

std::vector<USERPOINT> inputs; // input data 
std::vector<std::vector<POINT> > outputs; // space for output data 

const int thread_count = 4; 

struct work_packet {   // describe the work for one thread 
    USERPOINT *inputs;   // where to get its input 
    std::vector<POINT> *outputs; // where to put its output 
    int num_points;    // how many points to process 
    HANDLE finished;    // signal when it's done. 
}; 

std::vector<work_packet> packets(thread_count); // storage for the packets. 
std::vector<HANDLE> events(thread_count);  // storage for parent's handle to events 

outputs.resize(inputs.size);     // can't resize output after processing starts. 

for (int i=0; i<thread_count; i++) { 
    int offset = i * inputs.size()/thread_count; 
    packets[i].inputs = &inputs[0]+offset; 
    packets[i].outputs = &outputs[0]+offset; 
    packets[i].count = inputs.size()/thread_count; 
    events[i] = packets[i].done = CreateEvent(); 

    threads[i].process(&packets[i]); 
} 


// wait for curves to be generated (Win32 style, for the moment). 
WaitForMultipleObjects(&events[0], thread_count, WAIT_ALL, INFINITE); 

Notez que même si nous devons être sûrs que le vecteur outputs ne soit pas redimensionnée alors être exploité par plusieurs threads, les différents vecteurs de points de dans sorties peuvent être, parce que chacun sera seulement jamais être touché par un fil à la fois.

+3

+1 mais Note: Vous devrez peut-être utiliser des pointeurs sur les éléments du vecteur au lieu de passer le vecteur lui-même ici car les conteneurs STL peuvent être étranges en ce qui concerne le comportement multithread. –

+0

@Billy: Excellent point. –

+0

Je pense que la préoccupation de @Billy ONeal est suffisamment importante pour que vous en fassiez partie avant de vous donner un point. Un petit exemple de code serait également utile. – Omnifarious

-1

multithreading ne va pas accélérer votre processus. Traitement des données dans différents cœurs, pourrait.

+0

N'est-ce pas ce que fait le multithreading :-p – jmasterx

+0

Je pense que l'OP n'est pas stupide. Évidemment, l'intérêt d'utiliser plusieurs threads est d'utiliser plusieurs cœurs. –

0

Si la copie simple entre les choses est plus lente qu'avant de commencer à utiliser Mulitthreading, il est tout à fait probable que ce que vous faites ne sera pas échelonné sur plusieurs cœurs. Si c'est quelque chose de simple comme des trucs bezier, je pense que ça va être le cas. Rappelez-vous que le temps de fabrication des fils et autres a un impact sur le temps de fonctionnement total.

Enfin .. pour la copie, qu'est-ce que vous utilisez? Est-ce std::copy?

+0

std :: insert 4 fois – jmasterx

Questions connexes