一个使用TBB Lambda 表达式实现并行执行的例子(转)

来源:互联网 发布:穿越火线怎么优化 编辑:程序博客网 时间:2024/05/01 02:38

我曾经有一个用所有已知的方法来实现Pi的计算的例子,http://software.intel.com/en-us/blogs/2009/01/22/an-example-to-show-performance-data-for-different-implementations-of-pi-calculating/

现在Intel(R) Parallel Studio 中Composer 组件包含了最新的Threading Building Block 2.1 - 这个版本支持Lambda表达式,可以简化你的TBB代码。请注意新旧方法的异同。

#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <mmsystem.h>
#include <time.h>
#include <omp.h>

#include "tbb/task_scheduler_init.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/spin_mutex.h"
#include "tbb/tick_count.h"

using namespace tbb;
using namespace std;

const int num_steps = 100000000;
const int num_threads = 4; // My laptop is T61
double step = 0.0, pi = 0.0;

static tbb::spin_mutex myMutex;
static CRITICAL_SECTION cs;

void Serial_Pi()
{
   double x, sum = 0.0;
   int i;

   for (i=0; i< num_steps; i++){
      x = (i+0.5)*step;
      sum = sum + 4.0/(1.0 + x*x);
   }
   pi = step * sum;
}

DWORD WINAPI threadFunction(LPVOID pArg)
{

 double partialSum = 0.0, x;  // local to each thread
 int myNum = *((int *)pArg);

 for ( int i=myNum; i<num_steps; i+=num_threads )  // use every num_threads step
 {
  x = (i + 0.5)*step;
  partialSum += 4.0 / (1.0 + x*x);  //compute partial sums at each thread
 }

 EnterCriticalSection(&cs);
   pi += partialSum * step;  // add partial to global final answer

 LeaveCriticalSection(&cs);

 return 0;
}

void WinThread_Pi()
{
 HANDLE threadHandles[num_threads];
 int tNum[num_threads];

 InitializeCriticalSection(&cs);
 for ( int i=0; i<num_threads; ++i )
 {
  tNum[i] = i;
  threadHandles[i] = CreateThread( NULL,            // Security attributes
                                   0,               // Stack size
                                   threadFunction,  // Thread function
                                   (LPVOID)&tNum[i],// Data for thread func()
                                   0,               // Thread start mode
                                   NULL);           // Returned thread ID
 }
 WaitForMultipleObjects(num_threads, threadHandles, TRUE, INFINITE);

}

void OpenMP_Pi()
{
double x, sum=0.0;
int i;

omp_set_num_threads(4/*omp_get_thread_num()*/);
#pragma omp parallel for private (x) reduction(+:sum) //schedule(static,4)

 for (i=0; i<num_steps; i++)
 {
  x = (i + 0.5)*step;
  sum = sum + 4.0/(1. + x*x);
 }

 pi = sum*step;
}

class ParallelPi {
 
public:

 void operator() (tbb::blocked_range<int>& range) const {
  double x, sum = 0.0;
  for (int i = range.begin(); i < range.end(); ++i) {
   x = (i+0.5)*step;
   sum = sum + 4.0/(1.0 + x*x);
  }
  tbb::spin_mutex::scoped_lock lock(myMutex);
  pi += step * sum;
 }
};

void TBB_Pi ()
{
 parallel_for (tbb::blocked_range<int> (0, num_steps), ParallelPi(), tbb::auto_partitioner());
}

void TBB_Lambda_Pi()
{
 parallel_for(blocked_range<int>(0, num_steps, 5000 /*grain_size*/),
  [](const blocked_range<int> &r){
   double x, sum = 0.0;
   for (int i = r.begin(); i!=r.end(); ++i){
    x = (i + 0.5)*step;
    sum = sum + 4.0/(1. + x*x);
   };
   tbb::spin_mutex::scoped_lock lock(myMutex);
   pi += step *sum;
 });
 
}

int main()
{

 clock_t start, stop;

 // Coputing pi by using serial code
 pi = 0.0;
 step = 1.0/(double) num_steps;
 start = clock();
 Serial_Pi();
 stop = clock();
 printf ("Computed value of Pi by using serial code: %12.9f/n", pi);
 printf ("Elapsed time: %.2f seconds/n", (double)(stop-start)/1000.0);

 // Computing pi by using Windows Threads
 pi = 0.0;
 step = 1.0 / (double)num_steps;
 start = clock();
 WinThread_Pi();
 stop = clock();
 printf ("Computed value of Pi by using WinThreads: %12.9f/n", pi);
 printf ("Elapsed time: %.2f seconds/n", (double)(stop-start)/1000.0);
 
 // Computing pi by using OpenMP
 pi = 0.0;
 step = 1.0 / (double)num_steps;
 start = clock();
 OpenMP_Pi();
 stop = clock();
 printf ("Computed value of Pi by using OpenMP: %12.9f/n", pi);
 printf ("Elapsed time: %.2f seconds/n", (double)(stop-start)/1000.0);

 // Computing pi by using TBB
 pi = 0.0;
 step = 1.0 / (double)num_steps;
 start = clock();
 tbb::task_scheduler_init tbb_init;
 TBB_Pi();
 stop = clock();
 printf ("Computed value of Pi by using TBB: %12.9f/n", pi);
 printf ("Elapsed time: %.2f seconds/n", (double)(stop-start)/1000.0);

 // Computing pi by using TBB's Lambda
 pi = 0.0;
 step = 1.0 / (double)num_steps;
 start = clock();
// tbb::task_scheduler_init tbb_init;
 TBB_Lambda_Pi();
 stop = clock();
 printf ("Computed value of Pi by using TBB's Lambda: %12.9f/n", pi);
 printf ("Elapsed time: %.2f seconds/n", (double)(stop-start)/1000.0);
 
 return 0;
}

原创粉丝点击