⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fibonacci.cpp

📁 英特尔&#174 线程构建模块(英特尔&#174 TBB)是一个屡获殊荣的 C++ 运行时库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*    Copyright 2005-2007 Intel Corporation.  All Rights Reserved.    This file is part of Threading Building Blocks.    Threading Building Blocks is free software; you can redistribute it    and/or modify it under the terms of the GNU General Public License    version 2 as published by the Free Software Foundation.    Threading Building Blocks is distributed in the hope that it will be    useful, but WITHOUT ANY WARRANTY; without even the implied warranty    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with Threading Building Blocks; if not, write to the Free Software    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA    As a special exception, you may use this file as part of a free software    library without restriction.  Specifically, if other files instantiate    templates or use macros or inline functions from this file, or you compile    this file and link it with other files to produce an executable, this    file does not by itself cause the resulting executable to be covered by    the GNU General Public License.  This exception does not however    invalidate any other reasons why the executable file might be covered by    the GNU General Public License.*//* Example program that computes Fibonacci numbers in different ways.   Arguments are: [ Number [Threads [Repeats]]]   The defaults are Number=100 Threads=1:4 Repeats=1.   The point of this program is to check that the library is working properly.   Most of the computations are deliberately silly and not expected to   show any speedup on multiprocessors.*/#include <cstdio>#include <cstdlib>#include <cassert>#include <utility>#include "tbb/task.h"#include "tbb/task_scheduler_init.h"#include "tbb/tick_count.h"#include "tbb/blocked_range.h"#include "tbb/concurrent_vector.h"#include "tbb/concurrent_queue.h"#include "tbb/concurrent_hash_map.h"#include "tbb/parallel_while.h"#include "tbb/parallel_for.h"#include "tbb/parallel_reduce.h"#include "tbb/parallel_scan.h"#include "tbb/pipeline.h"#include "tbb/atomic.h"#include "tbb/mutex.h"#include "tbb/spin_mutex.h"#include "tbb/queuing_mutex.h"using namespace std;using namespace tbb;//! type used for Fibonacci number computationstypedef long long value;//! Matrix 2x2 classstruct Matrix2x2{    //! Array of values    value v[2][2];    Matrix2x2() {}    Matrix2x2(value v00, value v01, value v10, value v11) {        v[0][0] = v00; v[0][1] = v01; v[1][0] = v10; v[1][1] = v11;    }    Matrix2x2 operator * (const Matrix2x2 &to) const; //< Multiply two Matrices};//! Default matrix to multiplystatic const Matrix2x2 Matrix1110(1, 1, 1, 0);//! Raw arrays matrices multiplyvoid Matrix2x2Multiply(const value a[2][2], const value b[2][2], value c[2][2]);/////////////////////// Serial methods //////////////////////////! Plain serial sumvalue SerialFib(int n){    if(n < 2)        return n;    value a = 0, b = 1, sum; int i;    for( i = 2; i <= n; i++ )    {   // n is really index of Fibonacci number        sum = a + b; a = b; b = sum;    }    return sum;}//! Serial n-1 matrices multiplicationvalue SerialMatrixFib(int n){    value c[2][2], a[2][2] = {{1, 1}, {1, 0}}, b[2][2] = {{1, 1}, {1, 0}}; int i;    for(i = 2; i < n; i++)    {   // Using condition to prevent copying of values        if(i & 1) Matrix2x2Multiply(a, c, b);        else      Matrix2x2Multiply(a, b, c);    }    return (i & 1) ? c[0][0] : b[0][0]; // get result from upper left cell}//! Recursive summing. Just for complete list of serial algorithms, not usedvalue SerialRecursiveFib(int n){    value result;    if(n < 2)        result = n;    else        result = SerialRecursiveFib(n - 1) + SerialRecursiveFib(n - 2);    return result;}//! Introducing of queue method in serialvalue SerialQueueFib(int n){    concurrent_queue<Matrix2x2> Q;    for(int i = 1; i < n; i++)        Q.push(Matrix1110);    Matrix2x2 A, B;    while(true) {        Q.pop(A);        if(Q.empty()) break;        Q.pop(B);        Q.push(A * B);    }    return A.v[0][0];}//! Trying to use concurrent_vectorvalue SerialVectorFib(int n){    concurrent_vector<value> A;    A.grow_by(2);    A[0] = 0; A[1] = 1;    for( int i = 2; i <= n; i++)    {        A.grow_to_at_least(i+1);        A[i] = A[i-1] + A[i-2];    }    return A[n];}///////////////////// Parallel methods ////////////////////////// *** Serial shared by mutexes *** ////! Shared glabalsvalue SharedA = 0, SharedB = 1; int SharedI = 1, SharedN;//! Template task class which computes Fibonacci numbers with shared globalstemplate<typename M>class SharedSerialFibBody {    M &mutex;public:    SharedSerialFibBody( M &m ) : mutex( m ) {}    //! main loop    void operator()( const blocked_range<int>& range ) const {        for(;;) {            typename M::scoped_lock lock( mutex );            if(SharedI >= SharedN) break;            value sum = SharedA + SharedB;            SharedA = SharedB; SharedB = sum;            ++SharedI;        }    }};//! Root functiontemplate<class M>value SharedSerialFib(int n){    SharedA = 0; SharedB = 1; SharedI = 1; SharedN = n; M mutex;    parallel_for( blocked_range<int>(0,4,1), SharedSerialFibBody<M>( mutex ) );    return SharedB;}// *** Serial shared by concurrent hash *** ////! Hash comparerstruct IntHashCompare {    bool equal( const int j, const int k ) const { return j == k; }    unsigned long hash( const int k ) const { return (unsigned long)k; }   };//! NumbersTable type based on concurrent_hash_maptypedef concurrent_hash_map<int, value, IntHashCompare> NumbersTable;//! task for serial method using shared concurrent_hash_mapclass ConcurrentHashSerialFibTask: public task {    NumbersTable &Fib;    int my_n;public:    //! constructor    ConcurrentHashSerialFibTask( NumbersTable &cht, int n ) : Fib(cht), my_n(n) { }    //! executing task    /*override*/ task* execute()    {        for( int i = 2; i <= my_n; ++i ) { // there is no difference in to recycle or to make loop            NumbersTable::const_accessor f1, f2; // same as iterators            if( !Fib.find(f1, i-1) || !Fib.find(f2, i-2) ) {                // Something is seriously wrong, because i-1 and i-2 must have been inserted                 // earlier by this thread or another thread.                assert(0);            }            value sum = f1->second + f2->second;            NumbersTable::accessor fsum;            if(Fib.insert(fsum, i)) // inserting. is new element?                fsum->second = sum; // new, assign value            else                assert( fsum->second == sum ); // no, check value        }        return 0;    }};//! Root functionvalue ConcurrentHashSerialFib(int n){    NumbersTable Fib;     {   // We need to declare the accessor in a local block before using its values outside the block.        NumbersTable::accessor fref;        bool okay;        okay = Fib.insert(fref, 0); assert(okay); fref->second = 0; // assign initial values        okay = Fib.insert(fref, 1); assert(okay); fref->second = 1;        // Lifetime of fref ends here, which implicitly releases the write lock on what it points to.    }    task_list list;    // allocate tasks    list.push_back(*new(task::allocate_root()) ConcurrentHashSerialFibTask(Fib, n));    list.push_back(*new(task::allocate_root()) ConcurrentHashSerialFibTask(Fib, n));    task::spawn_root_and_wait(list);    NumbersTable::const_accessor fresult;    bool okay = Fib.find( fresult, n );    assert(okay);    return fresult->second;}// *** Queue with parallel_for and parallel_while *** ////! Stream of matricesstruct QueueStream {    volatile bool producer_is_done;    concurrent_queue<Matrix2x2> Queue;    //! Get pair of matricies if present    bool pop_if_present( pair<Matrix2x2, Matrix2x2> &mm ) {        // get first matrix if present        if(!Queue.pop_if_present(mm.first)) return false;        // get second matrix if present        if(!Queue.pop_if_present(mm.second)) {            // if not, then push back first matrix            Queue.push(mm.first); return false;        }        return true;    }};//! Functor for parallel_for which fills the queuestruct parallel_forFibBody {     QueueStream &my_stream;    //! fill functor arguments    parallel_forFibBody(QueueStream &s) : my_stream(s) { }    //! iterate thorough range    void operator()( const blocked_range<int> &range ) const {        int i_end = range.end();        for( int i = range.begin(); i != i_end; ++i ) {            my_stream.Queue.push( Matrix1110 ); // push initial matrix        }    }};//! Functor for parallel_while which process the queueclass parallel_whileFibBody{    QueueStream &my_stream;    parallel_while<parallel_whileFibBody> &my_while;public:    typedef pair<Matrix2x2, Matrix2x2> argument_type;    //! fill functor arguments    parallel_whileFibBody(parallel_while<parallel_whileFibBody> &w, QueueStream &s)        : my_while(w), my_stream(s) { }    //! process pair of matrices    void operator() (argument_type mm) const {        mm.first = mm.first * mm.second;        // note: it can run concurrently with QueueStream::pop_if_present()        if(my_stream.Queue.pop_if_present(mm.second))             my_while.add( mm ); // now, two matrices available. Add next iteration.        else my_stream.Queue.push( mm.first ); // or push back calculated value if queue is empty    }};//! Parallel queue's filling taskstruct QueueInsertTask: public task {    QueueStream &my_stream;    int my_n;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -