2012-05-15 11 views
17

Qualcuno mi può dare un esempio di come TBB:più semplice TBB esempio

  1. impostare il numero massimo di thread attivi.
  2. esegue attività indipendenti l'una dall'altra e presentate sotto forma di classe, non di funzioni statiche.

risposta

26

Ecco un paio di esempi completi, uno con parallel_for, l'altro con parallel_for_each.

Aggiornamento 2014-04-12: mostrano ciò che considero un modo piuttosto vecchio di utilizzare TBB ora; Ho aggiunto uno separate answer utilizzando parallel_for con un lambda C++ 11.

#include "tbb/blocked_range.h" 
#include "tbb/parallel_for.h" 
#include "tbb/task_scheduler_init.h" 
#include <iostream> 
#include <vector> 

struct mytask { 
    mytask(size_t n) 
    :_n(n) 
    {} 
    void operator()() { 
    for (int i=0;i<1000000;++i) {} // Deliberately run slow 
    std::cerr << "[" << _n << "]"; 
    } 
    size_t _n; 
}; 

struct executor 
{ 
    executor(std::vector<mytask>& t) 
    :_tasks(t) 
    {} 
    executor(executor& e,tbb::split) 
    :_tasks(e._tasks) 
    {} 

    void operator()(const tbb::blocked_range<size_t>& r) const { 
    for (size_t i=r.begin();i!=r.end();++i) 
     _tasks[i](); 
    } 

    std::vector<mytask>& _tasks; 
}; 

int main(int,char**) { 

    tbb::task_scheduler_init init; // Automatic number of threads 
    // tbb::task_scheduler_init init(2); // Explicit number of threads 

    std::vector<mytask> tasks; 
    for (int i=0;i<1000;++i) 
    tasks.push_back(mytask(i)); 

    executor exec(tasks); 
    tbb::parallel_for(tbb::blocked_range<size_t>(0,tasks.size()),exec); 
    std::cerr << std::endl; 

    return 0; 
} 

e

#include "tbb/parallel_for_each.h" 
#include "tbb/task_scheduler_init.h" 
#include <iostream> 
#include <vector> 

struct mytask { 
    mytask(size_t n) 
    :_n(n) 
    {} 
    void operator()() { 
    for (int i=0;i<1000000;++i) {} // Deliberately run slow 
    std::cerr << "[" << _n << "]"; 
    } 
    size_t _n; 
}; 

template <typename T> struct invoker { 
    void operator()(T& it) const {it();} 
}; 

int main(int,char**) { 

    tbb::task_scheduler_init init; // Automatic number of threads 
    // tbb::task_scheduler_init init(4); // Explicit number of threads 

    std::vector<mytask> tasks; 
    for (int i=0;i<1000;++i) 
    tasks.push_back(mytask(i)); 

    tbb::parallel_for_each(tasks.begin(),tasks.end(),invoker<mytask>()); 
    std::cerr << std::endl; 

    return 0; 
} 

Entrambi compilare su una Debian/Wheezy (g ++ 4.7) del sistema con g++ tbb_example.cpp -ltbb (quindi eseguire con ./a.out)

(Vedi this question per la sostituzione che "invoker" cosa con a std::mem_fun_ref o boost::bind).

15

Ecco un uso più moderno di parallel_for con una lambda; compilato ed eseguito su Debian/Wheezy con g++ -std=c++11 tbb_example.cpp -ltbb && ./a.out:

#include "tbb/parallel_for.h" 
#include "tbb/task_scheduler_init.h" 
#include <iostream> 
#include <vector> 

struct mytask { 
    mytask(size_t n) 
    :_n(n) 
    {} 
    void operator()() { 
    for (int i=0;i<1000000;++i) {} // Deliberately run slow 
    std::cerr << "[" << _n << "]"; 
    } 
    size_t _n; 
}; 

int main(int,char**) { 

    //tbb::task_scheduler_init init; // Automatic number of threads 
    tbb::task_scheduler_init init(tbb::task_scheduler_init::default_num_threads()); // Explicit number of threads 

    std::vector<mytask> tasks; 
    for (int i=0;i<1000;++i) 
    tasks.push_back(mytask(i)); 

    tbb::parallel_for(
    tbb::blocked_range<size_t>(0,tasks.size()), 
    [&tasks](const tbb::blocked_range<size_t>& r) { 
     for (size_t i=r.begin();i<r.end();++i) tasks[i](); 
    } 
); 

    std::cerr << std::endl; 

    return 0; 
} 
1

1-

//! 
//! Get the default number of threads 
//! 
int nDefThreads = tbb::task_scheduler_init::default_num_threads(); 

//! 
//! Init the task scheduler with the wanted number of threads 
//! 
tbb::task_scheduler_init init(nDefThreads); 

2-

Forse, se i vostri permessi di codice, il modo migliore per eseguire un'attività indipendente con TBB è la parallel_invoke . Nel blog della zona degli sviluppatori Intel c'è un post che spiega alcuni casi di come potrebbe essere utile parallel_invoke. Partenza this

2

Se si desidera eseguire contemporaneamente un paio di attività, potrebbe essere più semplice utilizzare solo lo tbb::task_group. Esempio tratto da tbb:

#include "tbb/task_group.h" 

using namespace tbb; 

int Fib(int n) { 
    if(n<2) { 
     return n; 
    } else { 
     int x, y; 
     task_group g; 
     g.run([&]{x=Fib(n-1);}); // spawn a task 
     g.run([&]{y=Fib(n-2);}); // spawn another task 
     g.wait();    // wait for both tasks to complete 
     return x+y; 
    } 
} 

Nota tuttavia che

Creazione di un gran numero di compiti per un singolo task_group non è scalabile, perché la creazione compito diventa un collo di bottiglia di serie.

In questi casi, utilizzare gli esempi di giorno con uno parallel_for o simili.