2012-05-15 35 views
17

Alguien me puede dar un ejemplo de cómo TBB:más simple TBB ejemplo

  1. establecer el número máximo de hebras activas.
  2. ejecutar tareas que son independientes entre sí y se presentan en forma de clase, no de funciones estáticas.

Respuesta

26

Aquí hay un par de ejemplos completos, uno usando parallel_for, el otro usando parallel_for_each.

Actualización 2014-04-12: Estas muestran lo que yo consideraría una forma bastante anticuada de usar TBB ahora; He agregado un separate answer usando parallel_for con un C++ 11 lambda.

#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; 
} 

y

#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; 
} 

Tanto compilar en un sistema Debian/Wheezy (g ++ 4.7) con g++ tbb_example.cpp -ltbb (a continuación, ejecutar con ./a.out)

(Ver this question para la sustitución de esa cosa "invoker" con a std::mem_fun_ref o boost::bind).

15

Aquí hay un uso más moderno de parallel_for con una lambda; compila y ejecuta en 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-

Tal vez si lo permite su código, la mejor forma de ejecutar tareas independiente con TBB es el parallel_invoke . En el blog de Intel developers zone hay una publicación que explica algunos casos de lo útil que podría ser parallel_invoke. Consulte this

2

Si solo desea ejecutar un par de tareas al mismo tiempo, podría ser más fácil simplemente usar un tbb::task_group. Ejemplo tomado de 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 sin embargo, que

La creación de un gran número de tareas para un solo task_group no es escalable, ya que la creación de tareas se convierte en un cuello de botella en serie.

En esos casos, use los ejemplos de timday con un parallel_for o similar.