| 1 | /* | 
|---|
| 2 | Copyright (c) 2005-2019 Intel Corporation | 
|---|
| 3 |  | 
|---|
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); | 
|---|
| 5 | you may not use this file except in compliance with the License. | 
|---|
| 6 | You may obtain a copy of the License at | 
|---|
| 7 |  | 
|---|
| 8 | http://www.apache.org/licenses/LICENSE-2.0 | 
|---|
| 9 |  | 
|---|
| 10 | Unless required by applicable law or agreed to in writing, software | 
|---|
| 11 | distributed under the License is distributed on an "AS IS" BASIS, | 
|---|
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|---|
| 13 | See the License for the specific language governing permissions and | 
|---|
| 14 | limitations under the License. | 
|---|
| 15 | */ | 
|---|
| 16 |  | 
|---|
| 17 | // Workaround for ICC 11.0 not finding __sync_fetch_and_add_4 on some of the Linux platforms. | 
|---|
| 18 | #if __linux__ && defined(__INTEL_COMPILER) | 
|---|
| 19 | #define __sync_fetch_and_add(ptr,addend) _InterlockedExchangeAdd(const_cast<void*>(reinterpret_cast<volatile void*>(ptr)), addend) | 
|---|
| 20 | #endif | 
|---|
| 21 | #include <string> | 
|---|
| 22 | #include <cstring> | 
|---|
| 23 | #include <cctype> | 
|---|
| 24 | #include <cstdlib> | 
|---|
| 25 | #include <cstdio> | 
|---|
| 26 | #include "tbb/concurrent_hash_map.h" | 
|---|
| 27 | #include "tbb/blocked_range.h" | 
|---|
| 28 | #include "tbb/parallel_for.h" | 
|---|
| 29 | #include "tbb/tick_count.h" | 
|---|
| 30 | #include "tbb/task_scheduler_init.h" | 
|---|
| 31 | #include "tbb/tbb_allocator.h" | 
|---|
| 32 | #include "../../common/utility/utility.h" | 
|---|
| 33 |  | 
|---|
| 34 |  | 
|---|
| 35 | //! String type with scalable allocator. | 
|---|
| 36 | /** On platforms with non-scalable default memory allocators, the example scales | 
|---|
| 37 | better if the string allocator is changed to tbb::tbb_allocator<char>. */ | 
|---|
| 38 | typedef std::basic_string<char,std::char_traits<char>,tbb::tbb_allocator<char> > MyString; | 
|---|
| 39 |  | 
|---|
| 40 | using namespace tbb; | 
|---|
| 41 | using namespace std; | 
|---|
| 42 |  | 
|---|
| 43 | //! Set to true to counts. | 
|---|
| 44 | static bool verbose = false; | 
|---|
| 45 | static bool silent = false; | 
|---|
| 46 | //! Problem size | 
|---|
| 47 | long N = 1000000; | 
|---|
| 48 | const int size_factor = 2; | 
|---|
| 49 |  | 
|---|
| 50 | //! A concurrent hash table that maps strings to ints. | 
|---|
| 51 | typedef concurrent_hash_map<MyString,int> StringTable; | 
|---|
| 52 |  | 
|---|
| 53 | //! Function object for counting occurrences of strings. | 
|---|
| 54 | struct Tally { | 
|---|
| 55 | StringTable& table; | 
|---|
| 56 | Tally( StringTable& table_ ) : table(table_) {} | 
|---|
| 57 | void operator()( const blocked_range<MyString*> range ) const { | 
|---|
| 58 | for( MyString* p=range.begin(); p!=range.end(); ++p ) { | 
|---|
| 59 | StringTable::accessor a; | 
|---|
| 60 | table.insert( a, *p ); | 
|---|
| 61 | a->second += 1; | 
|---|
| 62 | } | 
|---|
| 63 | } | 
|---|
| 64 | }; | 
|---|
| 65 |  | 
|---|
| 66 | static MyString* Data; | 
|---|
| 67 |  | 
|---|
| 68 | static void CountOccurrences(int nthreads) { | 
|---|
| 69 | StringTable table; | 
|---|
| 70 |  | 
|---|
| 71 | tick_count t0 = tick_count::now(); | 
|---|
| 72 | parallel_for( blocked_range<MyString*>( Data, Data+N, 1000 ), Tally(table) ); | 
|---|
| 73 | tick_count t1 = tick_count::now(); | 
|---|
| 74 |  | 
|---|
| 75 | int n = 0; | 
|---|
| 76 | for( StringTable::iterator i=table.begin(); i!=table.end(); ++i ) { | 
|---|
| 77 | if( verbose && nthreads ) | 
|---|
| 78 | printf( "%s %d\n",i->first.c_str(),i->second); | 
|---|
| 79 | n += i->second; | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | if ( !silent ) printf( "total = %d  unique = %u  time = %g\n", n, unsigned(table.size()), (t1-t0).seconds()); | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | /// Generator of random words | 
|---|
| 86 |  | 
|---|
| 87 | struct Sound { | 
|---|
| 88 | const char *chars; | 
|---|
| 89 | int rates[3];// beginning, middle, ending | 
|---|
| 90 | }; | 
|---|
| 91 | Sound Vowels[] = { | 
|---|
| 92 | { "e", {445,6220,1762}}, { "a", {704,5262,514}}, { "i", {402,5224,162}}, { "o", {248,3726,191}}, | 
|---|
| 93 | { "u", {155,1669,23}}, { "y", {4,400,989}}, { "io", {5,512,18}}, { "ia", {1,329,111}}, | 
|---|
| 94 | { "ea", {21,370,16}}, { "ou", {32,298,4}}, { "ie", {0,177,140}}, { "ee", {2,183,57}}, | 
|---|
| 95 | { "ai", {17,206,7}}, { "oo", {1,215,7}}, { "au", {40,111,2}}, { "ua", {0,102,4}}, | 
|---|
| 96 | { "ui", {0,104,1}}, { "ei", {6,94,3}}, { "ue", {0,67,28}}, { "ay", {1,42,52}}, | 
|---|
| 97 | { "ey", {1,14,80}}, { "oa", {5,84,3}}, { "oi", {2,81,1}}, { "eo", {1,71,5}}, | 
|---|
| 98 | { "iou", {0,61,0}}, { "oe", {2,46,9}}, { "eu", {12,43,0}}, { "iu", {0,45,0}}, | 
|---|
| 99 | { "ya", {12,19,5}}, { "ae", {7,18,10}}, { "oy", {0,10,13}}, { "ye", {8,7,7}}, | 
|---|
| 100 | { "ion", {0,0,20}}, { "ing", {0,0,20}}, { "ium", {0,0,10}}, { "er", {0,0,20}} | 
|---|
| 101 | }; | 
|---|
| 102 | Sound Consonants[] = { | 
|---|
| 103 | { "r", {483,1414,1110}}, { "n", {312,1548,1114}}, { "t", {363,1653,251}}, { "l", {424,1341,489}}, | 
|---|
| 104 | { "c", {734,735,260}}, { "m", {732,785,161}}, { "d", {558,612,389}}, { "s", {574,570,405}}, | 
|---|
| 105 | { "p", {519,361,98}}, { "b", {528,356,30}}, { "v", {197,598,16}}, { "ss", {3,191,567}}, | 
|---|
| 106 | { "g", {285,430,42}}, { "st", {142,323,180}}, { "h", {470,89,30}}, { "nt", {0,350,231}}, | 
|---|
| 107 | { "ng", {0,117,442}}, { "f", {319,194,19}}, { "ll", {1,414,83}}, { "w", {249,131,64}}, | 
|---|
| 108 | { "k", {154,179,47}}, { "nd", {0,279,92}}, { "bl", {62,235,0}}, { "z", {35,223,16}}, | 
|---|
| 109 | { "sh", {112,69,79}}, { "ch", {139,95,25}}, { "th", {70,143,39}}, { "tt", {0,219,19}}, | 
|---|
| 110 | { "tr", {131,104,0}}, { "pr", {186,41,0}}, { "nc", {0,223,2}}, { "j", {184,32,1}}, | 
|---|
| 111 | { "nn", {0,188,20}}, { "rt", {0,148,51}}, { "ct", {0,160,29}}, { "rr", {0,182,3}}, | 
|---|
| 112 | { "gr", {98,87,0}}, { "ck", {0,92,86}}, { "rd", {0,81,88}}, { "x", {8,102,48}}, | 
|---|
| 113 | { "ph", {47,101,10}}, { "br", {115,43,0}}, { "cr", {92,60,0}}, { "rm", {0,131,18}}, | 
|---|
| 114 | { "ns", {0,124,18}}, { "sp", {81,55,4}}, { "sm", {25,29,85}}, { "sc", {53,83,1}}, | 
|---|
| 115 | { "rn", {0,100,30}}, { "cl", {78,42,0}}, { "mm", {0,116,0}}, { "pp", {0,114,2}}, | 
|---|
| 116 | { "mp", {0,99,14}}, { "rs", {0,96,16}}, /*{"q", {52,57,1}},*/ { "rl", {0,97,7}}, | 
|---|
| 117 | { "rg", {0,81,15}}, { "pl", {56,39,0}}, { "sn", {32,62,1}}, { "str", {38,56,0}}, | 
|---|
| 118 | { "dr", {47,44,0}}, { "fl", {77,13,1}}, { "fr", {77,11,0}}, { "ld", {0,47,38}}, | 
|---|
| 119 | { "ff", {0,62,20}}, { "lt", {0,61,19}}, { "rb", {0,75,4}}, { "mb", {0,72,7}}, | 
|---|
| 120 | { "rc", {0,76,1}}, { "gg", {0,74,1}}, { "pt", {1,56,10}}, { "bb", {0,64,1}}, | 
|---|
| 121 | { "sl", {48,17,0}}, { "dd", {0,59,2}}, { "gn", {3,50,4}}, { "rk", {0,30,28}}, | 
|---|
| 122 | { "nk", {0,35,20}}, { "gl", {40,14,0}}, { "wh", {45,6,0}}, { "ntr", {0,50,0}}, | 
|---|
| 123 | { "rv", {0,47,1}}, { "ght", {0,19,29}}, { "sk", {23,17,5}}, { "nf", {0,46,0}}, | 
|---|
| 124 | { "cc", {0,45,0}}, { "ln", {0,41,0}}, { "sw", {36,4,0}}, { "rp", {0,36,4}}, | 
|---|
| 125 | { "dn", {0,38,0}}, { "ps", {14,19,5}}, { "nv", {0,38,0}}, { "tch", {0,21,16}}, | 
|---|
| 126 | { "nch", {0,26,11}}, { "lv", {0,35,0}}, { "wn", {0,14,21}}, { "rf", {0,32,3}}, | 
|---|
| 127 | { "lm", {0,30,5}}, { "dg", {0,34,0}}, { "ft", {0,18,15}}, { "scr", {23,10,0}}, | 
|---|
| 128 | { "rch", {0,24,6}}, { "rth", {0,23,7}}, { "rh", {13,15,0}}, { "mpl", {0,29,0}}, | 
|---|
| 129 | { "cs", {0,1,27}}, { "gh", {4,10,13}}, { "ls", {0,23,3}}, { "ndr", {0,25,0}}, | 
|---|
| 130 | { "tl", {0,23,1}}, { "ngl", {0,25,0}}, { "lk", {0,15,9}}, { "rw", {0,23,0}}, | 
|---|
| 131 | { "lb", {0,23,1}}, { "tw", {15,8,0}}, /*{"sq", {15,8,0}},*/ { "chr", {18,4,0}}, | 
|---|
| 132 | { "dl", {0,23,0}}, { "ctr", {0,22,0}}, { "nst", {0,21,0}}, { "lc", {0,22,0}}, | 
|---|
| 133 | { "sch", {16,4,0}}, { "ths", {0,1,20}}, { "nl", {0,21,0}}, { "lf", {0,15,6}}, | 
|---|
| 134 | { "ssn", {0,20,0}}, { "xt", {0,18,1}}, { "xp", {0,20,0}}, { "rst", {0,15,5}}, | 
|---|
| 135 | { "nh", {0,19,0}}, { "wr", {14,5,0}} | 
|---|
| 136 | }; | 
|---|
| 137 | const int VowelsNumber = sizeof(Vowels)/sizeof(Sound); | 
|---|
| 138 | const int ConsonantsNumber = sizeof(Consonants)/sizeof(Sound); | 
|---|
| 139 | int VowelsRatesSum[3] = {0,0,0}, ConsonantsRatesSum[3] = {0,0,0}; | 
|---|
| 140 |  | 
|---|
| 141 | int CountRateSum(Sound sounds[], const int num, const int part) | 
|---|
| 142 | { | 
|---|
| 143 | int sum = 0; | 
|---|
| 144 | for(int i = 0; i < num; i++) | 
|---|
| 145 | sum += sounds[i].rates[part]; | 
|---|
| 146 | return sum; | 
|---|
| 147 | } | 
|---|
| 148 |  | 
|---|
| 149 | const char *GetLetters(int type, const int part) | 
|---|
| 150 | { | 
|---|
| 151 | Sound *sounds; int rate, i = 0; | 
|---|
| 152 | if(type & 1) | 
|---|
| 153 | sounds = Vowels, rate = rand() % VowelsRatesSum[part]; | 
|---|
| 154 | else | 
|---|
| 155 | sounds = Consonants, rate = rand() % ConsonantsRatesSum[part]; | 
|---|
| 156 | do { | 
|---|
| 157 | rate -= sounds[i++].rates[part]; | 
|---|
| 158 | } while(rate > 0); | 
|---|
| 159 | return sounds[--i].chars; | 
|---|
| 160 | } | 
|---|
| 161 |  | 
|---|
| 162 | static void CreateData() { | 
|---|
| 163 | for(int i = 0; i < 3; i++) { | 
|---|
| 164 | ConsonantsRatesSum[i] = CountRateSum(Consonants, ConsonantsNumber, i); | 
|---|
| 165 | VowelsRatesSum[i] = CountRateSum(Vowels, VowelsNumber, i); | 
|---|
| 166 | } | 
|---|
| 167 | for( int i=0; i<N; ++i ) { | 
|---|
| 168 | int type = rand(); | 
|---|
| 169 | Data[i] = GetLetters(type++, 0); | 
|---|
| 170 | for( int j = 0; j < type%size_factor; ++j ) | 
|---|
| 171 | Data[i] += GetLetters(type++, 1); | 
|---|
| 172 | Data[i] += GetLetters(type, 2); | 
|---|
| 173 | } | 
|---|
| 174 | MyString planet = Data[12]; planet[0] = toupper(planet[0]); | 
|---|
| 175 | MyString helloworld = Data[0]; helloworld[0] = toupper(helloworld[0]); | 
|---|
| 176 | helloworld += ", "+Data[1]+ " "+Data[2]+ " "+Data[3]+ " "+Data[4]+ " "+Data[5]; | 
|---|
| 177 | if ( !silent ) printf( "Message from planet '%s': %s!\nAnalyzing whole text...\n", planet.c_str(), helloworld.c_str()); | 
|---|
| 178 | } | 
|---|
| 179 |  | 
|---|
| 180 | int main( int argc, char* argv[] ) { | 
|---|
| 181 | try { | 
|---|
| 182 | tbb::tick_count mainStartTime = tbb::tick_count::now(); | 
|---|
| 183 | srand(2); | 
|---|
| 184 |  | 
|---|
| 185 | //! Working threads count | 
|---|
| 186 | // The 1st argument is the function to obtain 'auto' value; the 2nd is the default value | 
|---|
| 187 | // The example interprets 0 threads as "run serially, then fully subscribed" | 
|---|
| 188 | utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads,0); | 
|---|
| 189 |  | 
|---|
| 190 | utility::parse_cli_arguments(argc,argv, | 
|---|
| 191 | utility::cli_argument_pack() | 
|---|
| 192 | //"-h" option for displaying help is present implicitly | 
|---|
| 193 | .positional_arg(threads, "n-of-threads",utility::thread_number_range_desc) | 
|---|
| 194 | .positional_arg(N, "n-of-strings", "number of strings") | 
|---|
| 195 | .arg(verbose, "verbose", "verbose mode") | 
|---|
| 196 | .arg(silent, "silent", "no output except elapsed time") | 
|---|
| 197 | ); | 
|---|
| 198 |  | 
|---|
| 199 | if ( silent ) verbose = false; | 
|---|
| 200 |  | 
|---|
| 201 | Data = new MyString[N]; | 
|---|
| 202 | CreateData(); | 
|---|
| 203 |  | 
|---|
| 204 | if ( threads.first ) { | 
|---|
| 205 | for(int p = threads.first;  p <= threads.last; p = threads.step(p)) { | 
|---|
| 206 | if ( !silent ) printf( "threads = %d  ", p ); | 
|---|
| 207 | task_scheduler_init init( p ); | 
|---|
| 208 | CountOccurrences( p ); | 
|---|
| 209 | } | 
|---|
| 210 | } else { // Number of threads wasn't set explicitly. Run serial and parallel version | 
|---|
| 211 | { // serial run | 
|---|
| 212 | if ( !silent ) printf( "serial run   "); | 
|---|
| 213 | task_scheduler_init init_serial(1); | 
|---|
| 214 | CountOccurrences(1); | 
|---|
| 215 | } | 
|---|
| 216 | { // parallel run (number of threads is selected automatically) | 
|---|
| 217 | if ( !silent ) printf( "parallel run "); | 
|---|
| 218 | task_scheduler_init init_parallel; | 
|---|
| 219 | CountOccurrences(0); | 
|---|
| 220 | } | 
|---|
| 221 | } | 
|---|
| 222 |  | 
|---|
| 223 | delete[] Data; | 
|---|
| 224 |  | 
|---|
| 225 | utility::report_elapsed_time((tbb::tick_count::now() - mainStartTime).seconds()); | 
|---|
| 226 |  | 
|---|
| 227 | return 0; | 
|---|
| 228 | } catch(std::exception& e) { | 
|---|
| 229 | std::cerr<< "error occurred. error text is :\""<<e.what()<< "\"\n"; | 
|---|
| 230 | } | 
|---|
| 231 | } | 
|---|
| 232 |  | 
|---|