00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "async-worker.h"
00010 #include <vector>
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <math.h>
00014 #include <time.h>
00015 #include <stdint.h>
00016
00017
00019 typedef uint64_t Number ;
00020
00022 typedef std::vector< Number > Numbers ;
00023
00025
00032
00033 class CrunchNumbersRange : public async::worker_t
00034 {
00042
00043 public: CrunchNumbersRange(const Numbers::iterator& start, const Numbers::iterator& end, Number* finalDestination)
00044 : worker_t()
00045 , m_start(start)
00046 , m_end(end)
00047 , m_sum(0)
00048 , m_finalDestination(finalDestination)
00049 {}
00050
00053 public: virtual void Work()
00054 {
00055 Numbers::iterator it ;
00056 for ( it = m_start ; it != m_end ; ++it )
00057 {
00058
00059
00060 double value = *it ;
00061 value = (value * 321.0234) + sin((float)value) + cos(std::min((float)value, (float)1.0)) + abs((float)value / (float)value) ;
00062 int x = (int)value % 2000000 ;
00063 value = value + (float) x ;
00064 x = (int)value % 3000000 ;
00065 value = (value + (float) x) / 3 ;
00066 x = (int)value % 4000000 ;
00067 value += x ;
00068 m_sum += (int)(value / (2 * 321)) % 999 + abs(sin((float)value / 100)) + abs(cos((float)value / 251)) ;
00069 }
00070 }
00071
00076 public: virtual void Result()
00077 {
00078
00079 *m_finalDestination += m_sum ;
00080 }
00081
00083 private: Numbers::iterator m_start, m_end ;
00085 private: mutable Number m_sum ;
00087 private: Number* m_finalDestination ;
00088
00089 } ;
00090
00091 #ifdef SHORT_VERSION
00092
00093 int main(int argc, const char* const argv[])
00094 {
00095 static const size_t NumberOfElements = 20000000 ;
00096 static const size_t GroupSize = 8192 ;
00097 Numbers numbers ;
00098 numbers.resize(NumberOfElements) ;
00099 for ( size_t i = 0 ; i < NumberOfElements ; ++i )
00100 {
00101 numbers[i] = (rand() & 65535) + 1 ;
00102 }
00103
00104 uint64_t parallelResult = 0 ;
00105
00106
00107 Numbers::iterator it = numbers.begin() ;
00108 do
00109 {
00110 Numbers::iterator end = std::min(it + GroupSize, numbers.end()) ;
00111 async::Queue(new CrunchNumbersRange(it, end, ¶llelResult)) ;
00112 it = end ;
00113 }
00114 while ( it != numbers.end() ) ;
00116
00118
00119
00120 async::GetResults() ;
00122
00123 printf("Done. Calculated sum as %lu.\n", (unsigned long int)parallelResult) ;
00124
00125 return 0 ;
00126 }
00127
00128 #endif
00129
00130
00131
00132 static unsigned long time_delta(const timespec& start, const timespec& end)
00133 {
00134 uint64_t usec = ((end.tv_sec * 1000000) + end.tv_nsec / 1000) - ((start.tv_sec * 1000000) + start.tv_nsec / 1000) ;
00135 return (unsigned long)(usec / 1000) ;
00136 }
00137
00138 int main(int argc, const char* const argv[])
00139 {
00140
00141 static const size_t NumberOfElements = 20000000 ;
00142 printf("Creating vector of %u numbers\n", NumberOfElements) ;
00143
00144
00145 Number serialResult = 0, parallelResult = 0 ;
00146
00147 Numbers numbers ;
00148
00149 numbers.resize(NumberOfElements) ;
00150 for ( size_t i = 0 ; i < NumberOfElements ; ++i )
00151 {
00152 numbers[i] = (rand() & 65535) + 1 ;
00153 }
00154
00155
00156 CrunchNumbersRange serial(numbers.begin(), numbers.end(), &serialResult) ;
00157
00158
00159 timespec timeStart, timeEnd ;
00160 unsigned long serialMsec, dispatchMsec, collectMsec ;
00161
00162 printf("Calculating sum serially...\n") ;
00163 clock_gettime(CLOCK_MONOTONIC, &timeStart) ;
00164
00165 serial.Work() ;
00166 serial.Result() ;
00167
00168 clock_gettime(CLOCK_MONOTONIC, &timeEnd) ;
00169 serialMsec = time_delta(timeStart, timeEnd) ;
00170 printf("Done. Calculated sum as %lu. Took %lums.\n", (unsigned long int)serialResult, serialMsec) ;
00171
00172 Numbers::iterator it = numbers.begin() ;
00173 static const size_t GroupSize = 8192 ;
00174
00175 printf("Dispatching %u workloads to background threads in groups of %u numbers per workload.\n", NumberOfElements / GroupSize, GroupSize) ;
00176
00177 clock_gettime(CLOCK_MONOTONIC, &timeStart) ;
00178
00180
00181 do
00182 {
00183 Numbers::iterator end = std::min(it + GroupSize, numbers.end()) ;
00184 async::Queue(new CrunchNumbersRange(it, end, ¶llelResult)) ;
00185 it = end ;
00186 }
00187 while ( it != numbers.end() ) ;
00189
00190 clock_gettime(CLOCK_MONOTONIC, &timeEnd) ;
00191 dispatchMsec = time_delta(timeStart, timeEnd) ;
00192 printf("Done. Took %lums.\n", dispatchMsec) ;
00193 printf("Collecting results.\n") ;
00194 clock_gettime(CLOCK_MONOTONIC, &timeStart) ;
00195
00197
00198
00199 async::GetResults() ;
00201
00202 clock_gettime(CLOCK_MONOTONIC, &timeEnd) ;
00203 collectMsec = time_delta(timeStart, timeEnd) ;
00204
00205 printf("Done. Calculated sum as %lu. Took %lums.\n", (unsigned long int)parallelResult, collectMsec) ;
00206
00207 unsigned long parallelMsec = dispatchMsec + collectMsec ;
00208 printf("Total time for parallel run: %lums.\n", parallelMsec) ;
00209
00210
00211 if ( parallelMsec >= serialMsec * 75 / 100 )
00212 {
00213 if ( parallelMsec > serialMsec )
00214 printf("Parallel run took %lums longer than serial.", parallelMsec - serialMsec) ;
00215 printf("Try adjusting GroupSize to increase parallel performance.\n") ;
00216 }
00217 else
00218 {
00219 printf("Parallel run took %lums less than serial version. Yay :)\n", serialMsec - parallelMsec) ;
00220 }
00221
00222 return 0 ;
00223 }
00224