![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright 2005-2010 Intel Corporation. All Rights Reserved. 00003 00004 This file is part of Threading Building Blocks. 00005 00006 Threading Building Blocks is free software; you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License 00008 version 2 as published by the Free Software Foundation. 00009 00010 Threading Building Blocks is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00012 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Threading Building Blocks; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 As a special exception, you may use this file as part of a free software 00020 library without restriction. Specifically, if other files instantiate 00021 templates or use macros or inline functions from this file, or you compile 00022 this file and link it with other files to produce an executable, this 00023 file does not by itself cause the resulting executable to be covered by 00024 the GNU General Public License. This exception does not however 00025 invalidate any other reasons why the executable file might be covered by 00026 the GNU General Public License. 00027 */ 00028 00029 /* Example program that shows how to use parallel_do to do parallel preorder 00030 traversal of a directed acyclic graph. */ 00031 00032 #include "tbb/parallel_do.h" 00033 #include "tbb/atomic.h" 00034 #include <vector> 00035 #include <algorithm> 00036 #include <cstring> 00037 #include <cstdio> 00038 #include "Graph.h" 00039 00040 using namespace std; 00041 00043 int ntrial = 50; 00044 00045 class Body { 00046 public: 00047 Body() {}; 00048 00049 //------------------------------------------------------------------------ 00050 // Following signatures are required by parallel_do 00051 //------------------------------------------------------------------------ 00052 typedef Cell* argument_type; 00053 00054 void operator()( Cell* c, tbb::parallel_do_feeder<Cell*>& feeder ) const { 00055 c->update(); 00056 // Restore ref_count in preparation for subsequent traversal. 00057 c->ref_count = ArityOfOp[c->op]; 00058 for( size_t k=0; k<c->successor.size(); ++k ) { 00059 Cell* successor = c->successor[k]; 00060 if( 0 == --(successor->ref_count) ) { 00061 feeder.add( successor ); 00062 } 00063 } 00064 } 00065 }; 00066 00067 void ParallelPreorderTraversal( const vector<Cell*>& root_set ) { 00068 tbb::parallel_do(root_set.begin(), root_set.end(),Body()); 00069 } 00070 00071 //------------------------------------------------------------------------ 00072 // Test driver 00073 //------------------------------------------------------------------------ 00074 00075 #include <cctype> 00076 #include "tbb/task_scheduler_init.h" 00077 #include "tbb/tick_count.h" 00078 00080 struct IntRange { 00081 int low; 00082 int high; 00083 void set_from_string( const char* s ); 00084 IntRange( int low_, int high_ ) : low(low_), high(high_) {} 00085 }; 00086 00087 void IntRange::set_from_string( const char* s ) { 00088 char* end; 00089 high = low = strtol(s,&end,0); 00090 switch( *end ) { 00091 case ':': 00092 high = strtol(end+1,0,0); 00093 break; 00094 case '\0': 00095 break; 00096 default: 00097 printf("unexpected character = %c\n",*end); 00098 } 00099 } 00100 00102 static IntRange NThread(1,4); 00103 00105 static bool PauseFlag = false; 00106 00108 void Usage(char * argv0) { 00109 fprintf(stderr, "Usage: %s [nthread [ntrials ['pause']]]\n", argv0); 00110 fprintf(stderr, "where nthread is a non-negative integer, or range of the form low:high [%d:%d]\n", NThread.low, NThread.high); 00111 fprintf(stderr, "ntrials is a positive integer. Default value is 50, reduce it (e.g. to 5) to shorten example run time\n"); 00112 fprintf(stderr, "The application waits for user to hit return if 'pause' is specified\n"); 00113 } 00114 00116 static void ParseCommandLine( int argc, char* argv[] ) { 00117 int i = 1; 00118 if( i<argc && !isdigit(argv[i][0]) ) { 00119 // Command line is garbled. 00120 Usage(argv[0]); 00121 exit(1); 00122 } 00123 if( i<argc ) 00124 NThread.set_from_string(argv[i++]); 00125 if( i<argc && !isdigit(argv[i][0]) ) { 00126 // Command line is garbled. 00127 Usage(argv[0]); 00128 exit(1); 00129 } 00130 if (i<argc) { 00131 ntrial = strtol(argv[i++], 0, 0); 00132 } 00133 if (ntrial == 0) { 00134 // Command line is garbled. 00135 Usage(argv[0]); 00136 exit(1); 00137 } 00138 if (i<argc && strcmp( argv[i], "pause" )==0 ) { 00139 PauseFlag = true; 00140 } 00141 } 00142 00143 int main( int argc, char* argv[] ) { 00144 ParseCommandLine(argc,argv); 00145 00146 // Start scheduler with given number of threads. 00147 for( int p=NThread.low; p<=NThread.high; ++p ) { 00148 tbb::task_scheduler_init init(p); 00149 srand(2); 00150 tbb::tick_count::interval_t interval; 00151 size_t total_root_set_size = 0; 00152 for( int trial=0; trial<ntrial; ++trial ) { 00153 Graph g; 00154 g.create_random_dag(1000); 00155 vector<Cell*> root_set; 00156 g.get_root_set(root_set); 00157 total_root_set_size += root_set.size(); 00158 00159 tbb::tick_count t0 = tbb::tick_count::now(); 00160 for( int i=0; i<10; ++i ) { 00161 ParallelPreorderTraversal(root_set); 00162 } 00163 tbb::tick_count t1 = tbb::tick_count::now(); 00164 00165 interval += t1-t0; 00166 } 00167 printf("%g seconds using %d threads (average of %g nodes in root_set)\n",interval.seconds(),p,(double)total_root_set_size/ntrial); 00168 } 00169 00170 if (PauseFlag) { 00171 printf ("Press return key to exit"); 00172 char c; 00173 int n = scanf("%c", &c); 00174 if( n!=1 ) { 00175 fprintf(stderr,"Fatal error: unexpected end of input\n"); 00176 exit(1); 00177 } 00178 } 00179 00180 return 0; 00181 }
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.