This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
ffnamespace:tutorial [2014/09/14 19:07] aldinuc |
ffnamespace:tutorial [2015/09/08 16:52] (current) torquati |
||
|---|---|---|---|
| Line 4: | Line 4: | ||
| ===== Tutorial ===== | ===== Tutorial ===== | ||
| - | * [[http://calvados.di.unipi.it/storage/tutorial/html/tutorial.html|Single HTML file]] (version August 2014) | + | * [[http://calvados.di.unipi.it/storage/tutorial/html/tutorial.html|Single HTML file]] (version September 2015) |
| - | * [[http://calvados.di.unipi.it/storage/tutorial/fftutorial.pdf|PDF file]] (version August 2014) | + | * [[http://calvados.di.unipi.it/storage/tutorial/fftutorial.pdf|PDF file]] (version September 2015) |
| - | * [[http://calvados.di.unipi.it/storage/tutorial/fftutorial_source_code.tgz | Tests and examples - source code (tarball)]] (version August 2014) | + | * [[http://calvados.di.unipi.it/storage/tutorial/fftutorial_source_code.tgz | Tests and examples - source code tarball]] (version September 2015) |
| ===== Very short Tutorial ===== | ===== Very short Tutorial ===== | ||
| Line 27: | Line 27: | ||
| <code c++> | <code c++> | ||
| /* this is a 3-stage pipeline example */ | /* this is a 3-stage pipeline example */ | ||
| + | #include <iostream> | ||
| #include <ff/pipeline.hpp> | #include <ff/pipeline.hpp> | ||
| using namespace ff; | using namespace ff; | ||
| typedef long fftask_t; | typedef long fftask_t; | ||
| - | struct firstStage: ff_node_t<task_t> { | + | struct firstStage: ff_node_t<fftask_t> { |
| fftask_t *svc(fftask_t *t) { | fftask_t *svc(fftask_t *t) { | ||
| for(long i=0;i<10;++i) ff_send_out(new fftask_t(i)); | for(long i=0;i<10;++i) ff_send_out(new fftask_t(i)); | ||
| Line 41: | Line 42: | ||
| return t; | return t; | ||
| } | } | ||
| - | struct thirdStage: ff_node_t<task_t> { | + | struct thirdStage: ff_node_t<fftask_t> { |
| fftask_t *svc(fftask_t *t) { | fftask_t *svc(fftask_t *t) { | ||
| std::cout << "stage" << get_my_id() << " received " << *t << "\n"; | std::cout << "stage" << get_my_id() << " received " << *t << "\n"; | ||
| Line 49: | Line 50: | ||
| }; | }; | ||
| int main() { | int main() { | ||
| - | ff_pipe<fftask_t> pipe(new firstStage, secondStage, new thirdStage); | + | ff_Pipe<> pipe(make_unique<firstStage>(), |
| - | pipe.cleanup_nodes(); // cleanup at exit | + | make_unique<ff_node_F<fftask_t> >(secondStage), |
| + | make_unique<thirdStage>() | ||
| + | ); | ||
| if (pipe.run_and_wait_end()<0) error("running pipe"); | if (pipe.run_and_wait_end()<0) error("running pipe"); | ||
| return 0; | return 0; | ||
| Line 70: | Line 73: | ||
| int main() { | int main() { | ||
| - | std::vector<ff_node*> W = {new thirdStage, new thirdStage}; // the farm has 2 workers | + | std::vector<std::unique_ptr<ff_node> > W; |
| - | ff_pipe<fftask_t> pipe(new firstStage, secondStage, new ff_farm<>(W)); | + | // the farm has 2 workers |
| - | pipe.cleanup_nodes(); | + | W.push_back( make_unique<thirdStage>()); |
| + | W.push_back( make_unique<thirdStage>()); | ||
| + | |||
| + | ff_Pipe<> pipe(make_unique<firstStage>(), | ||
| + | make_unique<ff_node_F<fftask_t> >(secondStage), | ||
| + | make_unique<ff_Farm<fftask_t> >(std::move(W)) | ||
| + | ); | ||
| if (pipe.run_and_wait_end()<0) error("running pipe"); | if (pipe.run_and_wait_end()<0) error("running pipe"); | ||
| return 0; | return 0; | ||
| Line 105: | Line 114: | ||
| === Data Dependency Tasks Executor (aka MDF) === | === Data Dependency Tasks Executor (aka MDF) === | ||
| - | TBD | + | The data-flow programming model is a general approach to parallelization |
| + | based upon data dependencies among a program's operations. The computations is expressed | ||
| + | by the data-flow graph, i.e. a DAG whose nodes are instructions and arcs are pure data dependencies. | ||
| + | If instead of simple instructions, portions of code (sets of instructions or functions) are used as graph's nodes, then it is called the macro data-flow model (MDF). It is worth noting that, the data-flow programming model is able to work both on stream of values and on a single value. | ||
| - | === Some valid combinations of pipeline and farm (and feedback) === | + | As an example, considering the [[http://en.wikipedia.org/wiki/Strassen_algorithm |Strassen's algorithm]] described by the following sequence of instructions operating on (sub-)matrices : |
| + | |||
| + | S1 = A11 + A22; S2 = B11 + B22; S3 = A21 + A22; S4 = B12 - B22; S5 = B21 - B11; | ||
| + | S6 = A11 + A12; S7 = A21 - A11; S8 = B11 + B12; S9 = A12 - A22; S10 = B21 + B22; | ||
| + | P1 = S1 * S2; P2 = S3 * B11; P3 = A11 * S4; P4 = A22 * S5; P5 = S6 * B22; P6 = S7 * S8; P7 = S9*S10 | ||
| + | C11 = P1 + P4 - P5 + P7; C12 = P3 + P5; C21 = P2 + P4; C22 = P1 - P2 + P3 + P6; | ||
| + | |||
| + | the resulting DAG is sketched in the following figure: | ||
| + | {{:ffnamespace:strassen.png?300|}} | ||
| + | |||
| + | The DAG's instructions can be executed in parallel simply respecting data dependencies. | ||
| + | ===== Some valid combinations of pipeline and farm (and feedback) ===== | ||
| {{:ffnamespace:composition2.png?400|}} | {{:ffnamespace:composition2.png?400|}} | ||