Shadowrun: Awakened 29 September 2011 - Build 871
count_strings.cpp
Go to the documentation of this file.
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 // Workaround for ICC 11.0 not finding __sync_fetch_and_add_4 on some of the Linux platforms.
00030 #if __linux__ && defined(__INTEL_COMPILER)
00031 #define __sync_fetch_and_add(ptr,addend) _InterlockedExchangeAdd(const_cast<void*>(reinterpret_cast<volatile void*>(ptr)), addend)
00032 #endif
00033 #include <string>
00034 #include <cstring>
00035 #include <cctype>
00036 #include <cstdlib>
00037 #include <cstdio>
00038 #include "tbb/concurrent_hash_map.h"
00039 #include "tbb/blocked_range.h"
00040 #include "tbb/parallel_for.h"
00041 #include "tbb/tick_count.h"
00042 #include "tbb/task_scheduler_init.h"
00043 #include "tbb/tbb_allocator.h"
00044 
00045 
00047 
00049 typedef std::basic_string<char,std::char_traits<char>,tbb::tbb_allocator<char> > MyString;
00050 
00051 using namespace tbb;
00052 using namespace std;
00053 
00055 static bool Verbose = false;
00056 
00058 static int NThread = 1;
00059 
00061 long N = 1000000;
00062 const int size_factor = 2;
00063 
00065 static bool is_number_of_threads_set = false;
00067 typedef concurrent_hash_map<MyString,int> StringTable;
00068 
00070 struct Tally {
00071     StringTable& table;
00072     Tally( StringTable& table_ ) : table(table_) {}
00073     void operator()( const blocked_range<MyString*> range ) const {
00074         for( MyString* p=range.begin(); p!=range.end(); ++p ) {
00075             StringTable::accessor a;
00076             table.insert( a, *p );
00077             a->second += 1;
00078         }
00079     }
00080 };
00081 
00082 static MyString* Data;
00083 
00084 static void CountOccurrences(int nthreads) {
00085     StringTable table;
00086 
00087     tick_count t0 = tick_count::now();
00088     parallel_for( blocked_range<MyString*>( Data, Data+N, 1000 ), Tally(table) );
00089     tick_count t1 = tick_count::now();
00090 
00091     int n = 0;
00092     for( StringTable::iterator i=table.begin(); i!=table.end(); ++i ) {
00093         if( Verbose && nthreads )
00094             printf("%s %d\n",i->first.c_str(),i->second);
00095         n += i->second;
00096     }
00097 
00098     if (is_number_of_threads_set) {
00099         printf("threads = %d  total = %d  unique = %u  time = %g\n", nthreads, n, unsigned(table.size()), (t1-t0).seconds());
00100     } else {
00101         if ( nthreads == 1 ) {
00102             printf("serial run   total = %d  unique = %u  time = %g\n", n, unsigned(table.size()), (t1-t0).seconds());
00103         } else {
00104             printf("parallel run total = %d  unique = %u  time = %g\n", n, unsigned(table.size()), (t1-t0).seconds());
00105         }
00106     }
00107 }
00108 
00110 
00111 struct Sound {
00112     const char *chars;
00113     int rates[3];// begining, middle, ending
00114 };
00115 Sound Vowels[] = {
00116     {"e", {445,6220,1762}}, {"a", {704,5262,514}}, {"i", {402,5224,162}}, {"o", {248,3726,191}},
00117     {"u", {155,1669,23}}, {"y", {4,400,989}}, {"io", {5,512,18}}, {"ia", {1,329,111}},
00118     {"ea", {21,370,16}}, {"ou", {32,298,4}}, {"ie", {0,177,140}}, {"ee", {2,183,57}},
00119     {"ai", {17,206,7}}, {"oo", {1,215,7}}, {"au", {40,111,2}}, {"ua", {0,102,4}},
00120     {"ui", {0,104,1}}, {"ei", {6,94,3}}, {"ue", {0,67,28}}, {"ay", {1,42,52}},
00121     {"ey", {1,14,80}}, {"oa", {5,84,3}}, {"oi", {2,81,1}}, {"eo", {1,71,5}},
00122     {"iou", {0,61,0}}, {"oe", {2,46,9}}, {"eu", {12,43,0}}, {"iu", {0,45,0}},
00123     {"ya", {12,19,5}}, {"ae", {7,18,10}}, {"oy", {0,10,13}}, {"ye", {8,7,7}},
00124     {"ion", {0,0,20}}, {"ing", {0,0,20}}, {"ium", {0,0,10}}, {"er", {0,0,20}}
00125 };
00126 Sound Consonants[] = {
00127     {"r", {483,1414,1110}}, {"n", {312,1548,1114}}, {"t", {363,1653,251}}, {"l", {424,1341,489}},
00128     {"c", {734,735,260}}, {"m", {732,785,161}}, {"d", {558,612,389}}, {"s", {574,570,405}},
00129     {"p", {519,361,98}}, {"b", {528,356,30}}, {"v", {197,598,16}}, {"ss", {3,191,567}},
00130     {"g", {285,430,42}}, {"st", {142,323,180}}, {"h", {470,89,30}}, {"nt", {0,350,231}},
00131     {"ng", {0,117,442}}, {"f", {319,194,19}}, {"ll", {1,414,83}}, {"w", {249,131,64}},
00132     {"k", {154,179,47}}, {"nd", {0,279,92}}, {"bl", {62,235,0}}, {"z", {35,223,16}},
00133     {"sh", {112,69,79}}, {"ch", {139,95,25}}, {"th", {70,143,39}}, {"tt", {0,219,19}},
00134     {"tr", {131,104,0}}, {"pr", {186,41,0}}, {"nc", {0,223,2}}, {"j", {184,32,1}},
00135     {"nn", {0,188,20}}, {"rt", {0,148,51}}, {"ct", {0,160,29}}, {"rr", {0,182,3}},
00136     {"gr", {98,87,0}}, {"ck", {0,92,86}}, {"rd", {0,81,88}}, {"x", {8,102,48}},
00137     {"ph", {47,101,10}}, {"br", {115,43,0}}, {"cr", {92,60,0}}, {"rm", {0,131,18}},
00138     {"ns", {0,124,18}}, {"sp", {81,55,4}}, {"sm", {25,29,85}}, {"sc", {53,83,1}},
00139     {"rn", {0,100,30}}, {"cl", {78,42,0}}, {"mm", {0,116,0}}, {"pp", {0,114,2}},
00140     {"mp", {0,99,14}}, {"rs", {0,96,16}}, /*{"q", {52,57,1}},*/ {"rl", {0,97,7}},
00141     {"rg", {0,81,15}}, {"pl", {56,39,0}}, {"sn", {32,62,1}}, {"str", {38,56,0}},
00142     {"dr", {47,44,0}}, {"fl", {77,13,1}}, {"fr", {77,11,0}}, {"ld", {0,47,38}},
00143     {"ff", {0,62,20}}, {"lt", {0,61,19}}, {"rb", {0,75,4}}, {"mb", {0,72,7}},
00144     {"rc", {0,76,1}}, {"gg", {0,74,1}}, {"pt", {1,56,10}}, {"bb", {0,64,1}},
00145     {"sl", {48,17,0}}, {"dd", {0,59,2}}, {"gn", {3,50,4}}, {"rk", {0,30,28}},
00146     {"nk", {0,35,20}}, {"gl", {40,14,0}}, {"wh", {45,6,0}}, {"ntr", {0,50,0}},
00147     {"rv", {0,47,1}}, {"ght", {0,19,29}}, {"sk", {23,17,5}}, {"nf", {0,46,0}},
00148     {"cc", {0,45,0}}, {"ln", {0,41,0}}, {"sw", {36,4,0}}, {"rp", {0,36,4}},
00149     {"dn", {0,38,0}}, {"ps", {14,19,5}}, {"nv", {0,38,0}}, {"tch", {0,21,16}},
00150     {"nch", {0,26,11}}, {"lv", {0,35,0}}, {"wn", {0,14,21}}, {"rf", {0,32,3}},
00151     {"lm", {0,30,5}}, {"dg", {0,34,0}}, {"ft", {0,18,15}}, {"scr", {23,10,0}},
00152     {"rch", {0,24,6}}, {"rth", {0,23,7}}, {"rh", {13,15,0}}, {"mpl", {0,29,0}},
00153     {"cs", {0,1,27}}, {"gh", {4,10,13}}, {"ls", {0,23,3}}, {"ndr", {0,25,0}},
00154     {"tl", {0,23,1}}, {"ngl", {0,25,0}}, {"lk", {0,15,9}}, {"rw", {0,23,0}},
00155     {"lb", {0,23,1}}, {"tw", {15,8,0}}, /*{"sq", {15,8,0}},*/ {"chr", {18,4,0}},
00156     {"dl", {0,23,0}}, {"ctr", {0,22,0}}, {"nst", {0,21,0}}, {"lc", {0,22,0}},
00157     {"sch", {16,4,0}}, {"ths", {0,1,20}}, {"nl", {0,21,0}}, {"lf", {0,15,6}},
00158     {"ssn", {0,20,0}}, {"xt", {0,18,1}}, {"xp", {0,20,0}}, {"rst", {0,15,5}},
00159     {"nh", {0,19,0}}, {"wr", {14,5,0}}
00160 };
00161 const int VowelsNumber = sizeof(Vowels)/sizeof(Sound);
00162 const int ConsonantsNumber = sizeof(Consonants)/sizeof(Sound);
00163 int VowelsRatesSum[3] = {0,0,0}, ConsonantsRatesSum[3] = {0,0,0};
00164 
00165 int CountRateSum(Sound sounds[], const int num, const int part)
00166 {
00167     int sum = 0;
00168     for(int i = 0; i < num; i++)
00169         sum += sounds[i].rates[part];
00170     return sum;
00171 }
00172 
00173 const char *GetLetters(int type, const int part)
00174 {
00175     Sound *sounds; int rate, i = 0;
00176     if(type & 1)
00177         sounds = Vowels, rate = rand() % VowelsRatesSum[part];
00178     else
00179         sounds = Consonants, rate = rand() % ConsonantsRatesSum[part];
00180     do {
00181         rate -= sounds[i++].rates[part];
00182     } while(rate > 0);
00183     return sounds[--i].chars;
00184 }
00185 
00186 static void CreateData() {
00187     for(int i = 0; i < 3; i++) {
00188         ConsonantsRatesSum[i] = CountRateSum(Consonants, ConsonantsNumber, i);
00189         VowelsRatesSum[i] = CountRateSum(Vowels, VowelsNumber, i);
00190     }
00191     for( int i=0; i<N; ++i ) {
00192         int type = rand();
00193         Data[i] = GetLetters(type++, 0);
00194         for( int j = 0; j < type%size_factor; ++j )
00195             Data[i] += GetLetters(type++, 1);
00196         Data[i] += GetLetters(type, 2);
00197     }
00198     MyString planet = Data[12]; planet[0] = toupper(planet[0]);
00199     MyString helloworld = Data[0]; helloworld[0] = toupper(helloworld[0]);
00200     helloworld += ", "+Data[1]+" "+Data[2]+" "+Data[3]+" "+Data[4]+" "+Data[5];
00201     printf("Message from planet '%s': %s!\nAnalyzing whole text...\n", planet.c_str(), helloworld.c_str());
00202 }
00203 
00205 
00206 static void ParseCommandLine( int argc, char* argv[] ) {
00207     int i = 1;
00208     if( i<argc && strcmp( argv[i], "verbose" )==0 ) {
00209         Verbose = true;
00210         ++i;
00211     }
00212     if( i<argc )
00213         if( !isdigit(argv[i][0]) ) {
00214             fprintf(stderr,"Usage: %s [verbose] [number-of-strings] [number-of-threads]\n",argv[0]);
00215             exit(1);
00216         } else {
00217             N = strtol(argv[i++],0,0);
00218         }
00219     if( i<argc )
00220         if( !isdigit(argv[i][0]) ) {
00221             fprintf(stderr,"Usage: %s [verbose] [number-of-strings] [number-of-threads]\n",argv[0]);
00222             exit(1);
00223         } else {
00224             NThread = strtol(argv[i++],0,0);
00225             is_number_of_threads_set = true;
00226         }
00227 }
00228 
00229 int main( int argc, char* argv[] ) {
00230     srand(2);
00231     ParseCommandLine( argc, argv );
00232     Data = new MyString[N];
00233     CreateData();
00234     if (is_number_of_threads_set) {
00235         task_scheduler_init init(NThread);
00236         CountOccurrences(NThread);
00237     } else { // Number of threads wasn't set explicitly. Run serial and parallel version
00238         { // serial run
00239             task_scheduler_init init_serial(1);
00240             CountOccurrences(1);
00241         }
00242         { // parallel run (number of threads is selected automatically)
00243             task_scheduler_init init_parallel;
00244             CountOccurrences(0);
00245         }
00246     }
00247     delete[] Data;
00248 }

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net