00001
00002
00003
00004
00005
00006 #include "async-worker.h"
00007 #include <vector>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <math.h>
00011 #include <time.h>
00012 #include <stdint.h>
00013
00014
00016 typedef uint64_t Number ;
00017
00019 typedef std::vector< Number > Numbers ;
00020
00022
00033
00034 class CrunchNumbersRange : public async::static_worker_t
00035 {
00037
00038 public: CrunchNumbersRange()
00039 : static_worker_t()
00040 , m_sum(0)
00041 {}
00042
00045 public: virtual void Work()
00046 {
00047 Numbers::iterator it ;
00048 for ( it = m_start ; it != m_end ; ++it )
00049 {
00050
00051
00052 double value = *it ;
00053 value = (value * 321.0234) + sin((float)value) + cos(std::min((float)value, (float)1.0)) + abs((float)value / (float)value) ;
00054 int x = (int)value % 2000000 ;
00055 value = value + (float) x ;
00056 x = (int)value % 3000000 ;
00057 value = (value + (float) x) / 3 ;
00058 x = (int)value % 4000000 ;
00059 value += x ;
00060 m_sum += (int)(value / (2 * 321)) % 999 + abs(sin((float)value / 100)) + abs(cos((float)value / 251)) ;
00061 }
00062 }
00063
00068 public: virtual void Result()
00069 {
00070
00071 *m_finalDestination += m_sum ;
00072 }
00073
00075 public: Numbers::iterator m_start, m_end ;
00077 private: mutable Number m_sum ;
00079 public: Number* m_finalDestination ;
00080
00081 } ;
00082
00083
00084 static unsigned long time_delta(const timespec& start, const timespec& end)
00085 {
00086 uint64_t usec = ((end.tv_sec * 1000000) + end.tv_nsec / 1000) - ((start.tv_sec * 1000000) + start.tv_nsec / 1000) ;
00087 return (unsigned long)(usec / 1000) ;
00088 }
00089
00090 int main(int argc, const char* const argv[])
00091 {
00092
00093 static const size_t NumberOfElements = 20000000 ;
00094 printf("Creating vector of %u numbers\n", NumberOfElements) ;
00095
00096
00097 Number serialResult = 0, parallelResult = 0 ;
00098
00099 Numbers numbers ;
00100
00101 numbers.resize(NumberOfElements) ;
00102 for ( size_t i = 0 ; i < NumberOfElements ; ++i )
00103 {
00104 numbers[i] = (rand() & 65535) + 1 ;
00105 }
00106
00107
00108 CrunchNumbersRange serial ;
00109 serial.m_start = numbers.begin() ;
00110 serial.m_end = numbers.end() ;
00111 serial.m_finalDestination = &serialResult ;
00112
00113
00114 timespec timeStart, timeEnd ;
00115 unsigned long serialMsec, dispatchMsec, collectMsec ;
00116
00117 printf("Calculating sum serially...\n") ;
00118 clock_gettime(CLOCK_MONOTONIC, &timeStart) ;
00119
00120 serial.Work() ;
00121 serial.Result() ;
00122
00123 clock_gettime(CLOCK_MONOTONIC, &timeEnd) ;
00124 serialMsec = time_delta(timeStart, timeEnd) ;
00125 printf("Done. Calculated sum as %lu. Took %lums.\n", (unsigned long int)serialResult, serialMsec) ;
00126
00127 Numbers::iterator it = numbers.begin() ;
00128 static const size_t GroupSize = 8192 ;
00129
00130 std::vector<CrunchNumbersRange> workloads ;
00131 workloads.resize((NumberOfElements + GroupSize - 1) / GroupSize) ;
00132
00133 printf("Dispatching %u workloads to background threads in groups of %u numbers per workload.\n", NumberOfElements / GroupSize, GroupSize) ;
00134
00135 clock_gettime(CLOCK_MONOTONIC, &timeStart) ;
00136
00137 std::vector<CrunchNumbersRange>::iterator workload ;
00138 for ( workload = workloads.begin() ; workload != workloads.end() ; ++workload )
00139 {
00140 Numbers::iterator end = std::min(it + GroupSize, numbers.end()) ;
00141 (*workload).m_start = it ;
00142 (*workload).m_end = end ;
00143 (*workload).m_finalDestination = ¶llelResult ;
00144 async::Queue(&(*workload)) ;
00145 it = end ;
00146 }
00147
00148 clock_gettime(CLOCK_MONOTONIC, &timeEnd) ;
00149 dispatchMsec = time_delta(timeStart, timeEnd) ;
00150 printf("Done. Took %lums.\n", dispatchMsec) ;
00151 printf("Collecting results.\n") ;
00152 clock_gettime(CLOCK_MONOTONIC, &timeStart) ;
00153
00154 async::GetResults() ;
00155
00156 clock_gettime(CLOCK_MONOTONIC, &timeEnd) ;
00157 collectMsec = time_delta(timeStart, timeEnd) ;
00158
00159 printf("Done. Calculated sum as %lu. Took %lums.\n", (unsigned long int)parallelResult, collectMsec) ;
00160
00161 unsigned long parallelMsec = dispatchMsec + collectMsec ;
00162 printf("Total time for parallel run: %lums.\n", parallelMsec) ;
00163
00164
00165 if ( parallelMsec >= serialMsec * 75 / 100 )
00166 {
00167 if ( parallelMsec > serialMsec )
00168 printf("Parallel run took %lums longer than serial.", parallelMsec - serialMsec) ;
00169 printf("Try adjusting GroupSize to increase parallel performance.\n") ;
00170 }
00171 else
00172 {
00173 printf("Parallel run took %lums less than serial version. Yay :)\n", serialMsec - parallelMsec) ;
00174 }
00175
00176 return 0 ;
00177 }
00178