2013-06-17 15 views
6

Muszę obsłużyć następujące scenerio: Mam 5 zadań ("A", "B", "C", "D", "E"), chciałbym je zrównoleglić, ale w odniesieniu do ich zależności. Muszą być wykonywane w takiej kolejności:Łańcuch zadań C++

A --> B --\ 
C ----------> E 
D --------/ 

So „E” jest wykonywany, gdy wszystkie wcześniejsze nich są wykończone i „B” musi być wykonane po A. I tu jest moje pytanie. Czy są jakieś gotowe rozwiązania (STL, Boost)? Czy będę musiał wdrożyć go w oparciu o std :: thread?

+0

Trzymaj się - Już to kiedyś widziałam? –

+7

Jeśli zostanie zaakceptowana [N3558] (http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf), myślę, że można to zrobić jako 'auto flow = std :: when_all (std :: async (A) .then (B), std :: async (C), std :: async (D)). then (std :: async (E)); '. – Xeo

+0

@Xeo Bardzo ładne! Właściwie możesz prawie zrobić to samo z Boost.Thread w Boost 1.54.0 (który jest obecnie w wersji beta), ale będziesz musiał zaimplementować metodę when_all. Dostarcza on .then() (jest niekompletny, ale jeśli nie musisz zmieniać executora, powinien działać). – Klaim

Odpowiedz

11

wymeldowanie TBB's Flow Graph lub PPL.

Przykład w łączu TBB pokazuje mniej więcej to, co zostało naszkicowane. Już sformułowałeś swój problem jako zadania. Nie musisz najpierw wchodzić na poziom wątku.

1

Możesz użyć std :: thread, którego nigdy nie używałem, ale wydaje się to całkiem proste.

Oto przykład prostego programu znalezionego na cppreference.com:

#include <iostream> 
#include <thread> 
#include <chrono> 

void foo() 
{ 
    // simulate expensive operation 
    std::this_thread::sleep_for(std::chrono::seconds(1)); 
} 

void bar() 
{ 
    // simulate expensive operation 
    std::this_thread::sleep_for(std::chrono::seconds(1)); 
} 

int main() 
{ 
    std::cout << "starting first helper...\n"; 
    std::thread helper1(foo); 

    std::cout << "starting second helper...\n"; 
    std::thread helper2(bar); 

    std::cout << "waiting for helpers to finish...\n"; 
    helper1.join(); 
    helper2.join(); 

    std::cout << "done!\n"; 
} 

Można użyć funkcji join(), aby czekać na wątek, aby zakończyć. Na przykład utworzysz nowy wątek, który wykona zadanie A. Następnie czekasz, aż się zakończy, zanim utworzysz nowy wątek, który wykona zadanie B.

Powinieneś skompilować z g ++ -std = C++ 0x - pthread main.cpp

Alternatywnie można wyszukiwać pliki MPI i OpenMP, które mogą zapewnić pewne możliwości std :: thread can not.

2

Myślę, że można to zrobić za pomocą dyrektywy OpenMP section, którą można wykonać za pomocą ICC, GCC i MSVC. Dyrektywa OpenMP task jest prawdopodobnie lepszym wyborem i można ją wykonać za pomocą ICC i GCC, ale nie w żadnej wersji MSVC.

Poniższy kod wykorzystuje OpenMP sections. Ponieważ E jest uruchamiane po zakończeniu wszystkich innych zadań, możliwe jest jego równoległe wykonanie, dlatego następujący kod E jest uruchamiany przez wszystkie wątki po zakończeniu A, B, C, D. Jeśli E jest iteracją przez pętlę, możesz w ten sposób zrównoleglić pętlę. Nie jestem pewien, czy tego chcesz, ale możesz łatwo uruchomić go w jednym wątku, jak chcesz.

#include <stdio.h> 
#include <omp.h> 

void A() { printf("A\n"); } 
void B() { printf("B\n"); } 
void C() { printf("C\n"); } 
void D() { printf("D\n"); } 
void E() { 
    printf("E: %d\n", omp_get_thread_num()); 
    #pragma omp for 
    for(int i=0; i<10; i++) { 
    //do something as a function of i 
    } 
} 

void foo() { 
#pragma omp parallel // starts a new team 
{ 
    #pragma omp sections // divides the team into sections 
    { 
    { A(); B(); } 
    #pragma omp section 
    { C(); } 
    #pragma omp section 
    { D(); } 
    } 
    E(); 
} 
} 

int main() { 
    foo(); 
} 
Powiązane problemy