intel线程库tbb的使用

 首先下载:

http://www.threadingbuildingblocks.org/uploads/77/111/2.1/tbb21_20080605oss_win.zip

当前是2.1版本

解压到c盘,打开vs2005,设置vc++的项目目录

include:

C:/tbb21oss_win/include

执行文件:

C:/tbb21oss_win/ia32/vc8/bin

库文件:

C:/tbb21oss_win/ia32/vc8/lib

最后设置 我的电脑--环境变量设置

添加下面到path部分的最前面,记得加上一个“;”:C:/tbb21oss_win/ia32/vc8/bin

然后添加一个变量:

TBB21_INSTALL_DIR 为C:/tbb21oss_win

开启vs2005的命令行工具,进入到C:/tbb21oss_win/ia32/vc8/bin路径,执行tbbvars.bat文件

 

可以开始第一个程序了,记得带上tbb.lib对应的是release编译模式

  1. /*
  2.     Copyright 2005-2008 Intel Corporation.  All Rights Reserved.
  3.     This file is part of Threading Building Blocks.
  4.     Threading Building Blocks is free software; you can redistribute it
  5.     and/or modify it under the terms of the GNU General Public License
  6.     version 2 as published by the Free Software Foundation.
  7.     Threading Building Blocks is distributed in the hope that it will be
  8.     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  9.     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.     GNU General Public License for more details.
  11.     You should have received a copy of the GNU General Public License
  12.     along with Threading Building Blocks; if not, write to the Free Software
  13.     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  14.     As a special exception, you may use this file as part of a free software
  15.     library without restriction.  Specifically, if other files instantiate
  16.     templates or use macros or inline functions from this file, or you compile
  17.     this file and link it with other files to produce an executable, this
  18.     file does not by itself cause the resulting executable to be covered by
  19.     the GNU General Public License.  This exception does not however
  20.     invalidate any other reasons why the executable file might be covered by
  21.     the GNU General Public License.
  22. */
  23. //
  24. // Example program that reads a file of text and changes the first letter
  25. // of each word to upper case.
  26. // 
  27. #include "tbb/pipeline.h"
  28. #include "tbb/tick_count.h"
  29. #include "tbb/task_scheduler_init.h"
  30. #include <cstring>
  31. #include <cstdlib>
  32. #include <cstdio>
  33. #include <cctype>
  34. using namespace std;
  35. //! Buffer that holds block of characters and last character of previous buffer.
  36. class MyBuffer {
  37.     static const size_t buffer_size = 10000;
  38.     char* my_end;
  39.     //! storage[0] holds the last character of the previous buffer.
  40.     char storage[1+buffer_size];
  41. public:
  42.     //! Pointer to first character in the buffer
  43.     char* begin() {return storage+1;}
  44.     const char* begin() const {return storage+1;}
  45.     //! Pointer to one past last character in the buffer
  46.     char* end() const {return my_end;}
  47.     //! Set end of buffer.
  48.     void set_end( char* new_ptr ) {my_end=new_ptr;}
  49.     //! Number of bytes a buffer can hold
  50.     size_t max_size() const {return buffer_size;}
  51.     //! Number of bytes appended to buffer.
  52.     size_t size() const {return my_end-begin();}
  53. };
  54. class MyInputFilter: public tbb::filter {
  55. public:
  56.     static const size_t n_buffer = 8;
  57.     MyInputFilter( FILE* input_file_ );
  58. private:
  59.     FILE* input_file;
  60.     size_t next_buffer;
  61.     char last_char_of_previous_buffer;
  62.     MyBuffer buffer[n_buffer];
  63.     /*override*/ voidoperator()(void*);
  64. };
  65. MyInputFilter::MyInputFilter( FILE* input_file_ ) : 
  66.     filter(/*is_serial=*/true),
  67.     next_buffer(0),
  68.     input_file(input_file_),
  69.     last_char_of_previous_buffer(' ')
  70. }
  71. void* MyInputFilter::operator()(void*) {
  72.     MyBuffer& b = buffer[next_buffer];
  73.     next_buffer = (next_buffer+1) % n_buffer;
  74.     size_t n = fread( b.begin(), 1, b.max_size(), input_file );
  75.     if( !n ) {
  76.         // end of file
  77.         return NULL;
  78.     } else {
  79.         b.begin()[-1] = last_char_of_previous_buffer;
  80.         last_char_of_previous_buffer = b.begin()[n-1];
  81.         b.set_end( b.begin()+n );
  82.         return &b;
  83.     }
  84. }
  85. //! Filter that changes the first letter of each word from lower case to upper case.
  86. class MyTransformFilter: public tbb::filter {
  87. public:
  88.     MyTransformFilter();
  89.     /*override*/voidoperator()( void* item );
  90. };
  91. MyTransformFilter::MyTransformFilter() : 
  92.     tbb::filter(/*ordered=*/false
  93. {}  
  94. /*override*/void* MyTransformFilter::operator()( void* item ) {
  95.     MyBuffer& b = *static_cast<MyBuffer*>(item);
  96.     int prev_char_is_space = b.begin()[-1]==' ';
  97.     forchar* s=b.begin(); s!=b.end(); ++s ) {
  98.         if( prev_char_is_space && islower((unsigned char)*s) )
  99.             *s = toupper(*s);
  100.         prev_char_is_space = isspace((unsigned char)*s);
  101.     }
  102.     return &b;  
  103. }
  104.          
  105. //! Filter that writes each buffer to a file.
  106. class MyOutputFilter: public tbb::filter {
  107.     FILE* my_output_file;
  108. public:
  109.     MyOutputFilter( FILE* output_file );
  110.     /*override*/voidoperator()( void* item );
  111. };
  112. MyOutputFilter::MyOutputFilter( FILE* output_file ) : 
  113.     tbb::filter(/*is_serial=*/true),
  114.     my_output_file(output_file)
  115. {
  116. }
  117. void* MyOutputFilter::operator()( void* item ) {
  118.     MyBuffer& b = *static_cast<MyBuffer*>(item);
  119.     fwrite( b.begin(), 1, b.size(), my_output_file );
  120.     return NULL;
  121. }
  122. static int NThread = tbb::task_scheduler_init::automatic;
  123. static const char* InputFileName = "input.txt";
  124. static const char* OutputFileName = "output.txt";
  125. static bool is_number_of_threads_set = false;
  126. void Usage()
  127. {
  128.     fprintf( stderr, "Usage:/ttext_filter [input-file [output-file [nthread]]]/n");
  129. }
  130. int ParseCommandLine(  int argc, char* argv[] ) {
  131.     // Parse command line
  132.     if( argc> 4 ){
  133.         Usage();
  134.         return 0;
  135.     }
  136.     if( argc>=2 ) InputFileName = argv[1];
  137.     if( argc>=3 ) OutputFileName = argv[2];
  138.     if( argc>=4 ) {
  139.         NThread = strtol(argv[3],0,0);
  140.         if( NThread<1 ) {
  141.             fprintf(stderr,"nthread set to %d, but must be at least 1/n",NThread);
  142.             return 0;
  143.         }
  144.         is_number_of_threads_set = true//Number of threads is set explicitly
  145.     }
  146.     return 1;
  147. }
  148. int run_pipeline( int nthreads )
  149. {
  150.     FILE* input_file = fopen(InputFileName,"r");
  151.     if( !input_file ) {
  152.         perror( InputFileName );
  153.         Usage();
  154.         return 0;
  155.     }
  156.     FILE* output_file = fopen(OutputFileName,"w");
  157.     if( !output_file ) {
  158.         perror( OutputFileName );
  159.         return 0;
  160.     }
  161.     // Create the pipeline
  162.     tbb::pipeline pipeline;
  163.     // Create file-reading writing stage and add it to the pipeline
  164.     MyInputFilter input_filter( input_file );
  165.     pipeline.add_filter( input_filter );
  166.     // Create capitalization stage and add it to the pipeline
  167.     MyTransformFilter transform_filter; 
  168.     pipeline.add_filter( transform_filter );
  169.     // Create file-writing stage and add it to the pipeline
  170.     MyOutputFilter output_filter( output_file );
  171.     pipeline.add_filter( output_filter );
  172.     // Run the pipeline
  173.     tbb::tick_count t0 = tbb::tick_count::now();
  174.     pipeline.run( MyInputFilter::n_buffer );
  175.     tbb::tick_count t1 = tbb::tick_count::now();
  176.     // Remove filters from pipeline before they are implicitly destroyed.
  177.     pipeline.clear(); 
  178.     fclose( output_file );
  179.     fclose( input_file );
  180.     if (is_number_of_threads_set) {
  181.         printf("threads = %d time = %g/n", nthreads, (t1-t0).seconds());
  182.     } else {
  183.         if ( nthreads == 1 ){
  184.             printf("serial run   time = %g/n", (t1-t0).seconds());
  185.         } else {
  186.             printf("parallel run time = %g/n", (t1-t0).seconds());
  187.         }
  188.     }
  189.     return 1;
  190. }
  191. int main( int argc, char* argv[] ) {
  192.     if(!ParseCommandLine( argc, argv ))
  193.         return 1;
  194.     if (is_number_of_threads_set) {
  195.         // Start task scheduler
  196.         tbb::task_scheduler_init init( NThread );
  197.         if(!run_pipeline (NThread))
  198.             return 1;
  199.     } else { // Number of threads wasn't set explicitly. Run serial and parallel version
  200.         { // serial run
  201.             tbb::task_scheduler_init init_serial(1);
  202.             if(!run_pipeline (1))
  203.                 return 1;
  204.         }
  205.         { // parallel run (number of threads is selected automatically)
  206.             tbb::task_scheduler_init init_parallel;
  207.             if(!run_pipeline (0))
  208.                 return 1;
  209.         }
  210.     }
  211.     return 0;
  212. }

 

第二个程序,对应debug模式,带上tbb_debug.lib:

  1. #include "tbb/task_scheduler_init.h"
  2. #include "tbb/blocked_range.h"
  3. #include "tbb/parallel_for.h"
  4. // 链接tbb_debug.lib
  5. //#pragma comment(lib, "tbb_debug.lib")
  6. using namespace tbb;
  7. // 对每个Item执行该操作
  8. void Foo(float value)
  9. {
  10.     printf("%.2f/n ", value);
  11. }
  12. class ApplyFoo
  13.     {
  14.         float * const my_a;
  15. public:
  16.     void operator () (const blocked_range<size_t> & r) const
  17.         {
  18.             float * a = my_a;
  19.             for (size_t i = r.begin(); i != r.end(); ++ i)
  20.                 Foo(a[i]);
  21.     }
  22.     ApplyFoo(float a[]) : my_a(a) {}
  23. };
  24. int _tmain(int argc, _TCHAR* argv[])
  25. {
  26.     // 创建task scheduler
  27.     // task_scheduler_init支持一个参数,以指定使用的线程数
  28.     task_scheduler_init init;
  29.     float a[100];
  30.     for (int i = 0; i < 100; i ++)
  31.         a[i] = (float)i;
  32.     // TBB会把数组分成若干的block
  33.     // 对block调用ApplyFoo这个functor
  34.     parallel_for(blocked_range<size_t>(0, 100), ApplyFoo(a));
  35.     return 0;
  36. }

你可能感兴趣的:(filter,File,buffer,input,output,functor)