Mercurial > cgi-bin > hgwebdir.cgi > PR > Applications > pthread > pthread__k_tuple__async
diff src/Application/main.c @ 0:9cf9b2091eeb
working condition variable version
| author | Sean Halle <seanhalle@yahoo.com> |
|---|---|
| date | Wed, 10 Jul 2013 14:13:46 -0700 |
| parents | |
| children | 88db7b62b961 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/Application/main.c Wed Jul 10 14:13:46 2013 -0700 1.3 @@ -0,0 +1,277 @@ 1.4 +/* 1.5 + * 1.6 + */ 1.7 + 1.8 +#include "main.h" 1.9 + 1.10 +//========== Global Vars =========== 1.11 + 1.12 +const char *usage = 1.13 + { 1.14 + "Usage: k_tuple_async [options]\n" 1.15 + " Creates a number of workers, and one consumer that packages productions " 1.16 + " into a tuple.\n\n" 1.17 + "Options:\n" 1.18 + " -p <num> The number of producer threads to create.\n" 1.19 + " -t <num> the number of tuples to create\n" 1.20 + " -h this help screen\n\n" 1.21 + }; 1.22 + 1.23 +char __ProgrammName[] = "K-tuple_async"; 1.24 +char __DataSet[255]; 1.25 + 1.26 +#ifdef MEASURE_PERF 1.27 +int cycles_counter_fd[NUM_CORES]; 1.28 +int instrs_counter_fd[NUM_CORES]; 1.29 +int cycles_counter_main_fd; 1.30 +#endif 1.31 + 1.32 +pthread_mutex_t waitForAllDoneLock; 1.33 +pthread_cond_t waitForAllDoneCond; 1.34 + 1.35 + 1.36 +//=================================== 1.37 +/* provide a millisecond-resolution timer for each system */ 1.38 +#if defined(unix) || defined(__unix__) 1.39 +#include <time.h> 1.40 +#include <sys/time.h> 1.41 +unsigned long get_msec(void) { 1.42 + static struct timeval timeval, first_timeval; 1.43 + 1.44 + gettimeofday(&timeval, 0); 1.45 + if(first_timeval.tv_sec == 0) { 1.46 + first_timeval = timeval; 1.47 + return 0; 1.48 + } 1.49 + return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000; 1.50 +} 1.51 +#elif defined(__WIN32__) || defined(WIN32) 1.52 +#include <windows.h> 1.53 +unsigned long get_msec(void) { 1.54 + return GetTickCount(); 1.55 +} 1.56 +#else 1.57 +#error "I don't know how to measure time on your platform" 1.58 +#endif 1.59 + 1.60 +/*Initializes the performance counters, and opens the file descriptors used 1.61 + * to read from the performance counters 1.62 + */ 1.63 +void 1.64 +set_up_performance_counters() 1.65 + { int i; 1.66 + 1.67 + #ifdef MEASURE_PERF 1.68 + //setup performance counters 1.69 + struct perf_event_attr hw_event; 1.70 + memset(&hw_event,0,sizeof(hw_event)); 1.71 + hw_event.type = PERF_TYPE_HARDWARE; 1.72 + hw_event.size = sizeof(hw_event); 1.73 + hw_event.disabled = 0; 1.74 + hw_event.freq = 0; 1.75 + hw_event.inherit = 1; /* children inherit it */ 1.76 + hw_event.pinned = 1; /* must always be on PMU */ 1.77 + hw_event.exclusive = 0; /* only group on PMU */ 1.78 + hw_event.exclude_user = 0; /* don't count user */ 1.79 + hw_event.exclude_kernel = 1; /* ditto kernel */ 1.80 + hw_event.exclude_hv = 1; /* ditto hypervisor */ 1.81 + hw_event.exclude_idle = 1; /* don't count when idle */ 1.82 + hw_event.mmap = 0; /* include mmap data */ 1.83 + hw_event.comm = 0; /* include comm data */ 1.84 + 1.85 + 1.86 + for( i = 0; i < NUM_CORES; i++ ) 1.87 + { 1.88 + hw_event.config = PERF_COUNT_HW_CPU_CYCLES; //cycles 1.89 + cycles_counter_fd[i] = syscall(__NR_perf_event_open, &hw_event, 1.90 + 0,//pid_t pid, 1.91 + i,//int cpu, 1.92 + -1,//int group_fd, 1.93 + 0//unsigned long flags 1.94 + ); 1.95 + if (cycles_counter_fd[i]<0){ 1.96 + fprintf(stderr,"On core %d: ",i); 1.97 + perror("Failed to open cycles counter"); 1.98 + } 1.99 + } 1.100 + 1.101 + int cycles_counter_main_fd; 1.102 + hw_event.config = PERF_COUNT_HW_CPU_CYCLES; //cycles 1.103 + hw_event.exclude_kernel=0; 1.104 + cycles_counter_main_fd = syscall(__NR_perf_event_open, &hw_event, 1.105 + 0,//pid_t pid, 1.106 + -1,//int cpu, 1.107 + -1,//int group_fd, 1.108 + 0//unsigned long flags 1.109 + ); 1.110 + if (cycles_counter_main_fd<0){ 1.111 + perror("Failed to open main cycles counter"); 1.112 + } 1.113 + 1.114 + #endif 1.115 + } 1.116 + 1.117 + 1.118 +void 1.119 +init_stuff() 1.120 + { 1.121 + pthread_mutex_init(&tupleIterLock, NULL); 1.122 + pthread_cond_init( &tupleIterCond, NULL ); 1.123 + tupleIter = 0; 1.124 + 1.125 + pthread_mutex_init(&producerAccessMutex, NULL); 1.126 + pthread_mutex_init(&productionReadyLock, NULL); 1.127 + pthread_cond_init( &productionReadyCond, NULL ); 1.128 + currProductionNum = 0; 1.129 + 1.130 + pthread_mutex_init(&consumerReceivedAckLock, NULL); 1.131 + pthread_cond_init( &consumerReceivedAckCond, NULL ); 1.132 + currConsumerReceivedACKNum = 0; 1.133 + } 1.134 + 1.135 + 1.136 +typedef struct 1.137 + { 1.138 + int numProducers; 1.139 + int numTuplesToCreate; 1.140 + } 1.141 +ParsedArgs; 1.142 + 1.143 +/*The benchmark Fn creates the producers and the consumer, then gives the 1.144 + * "go" signal. It measures time from go until the consumer produces the 1.145 + * last tuple as output. 1.146 + */ 1.147 +void 1.148 +benchmark( ParsedArgs *args ) 1.149 + { 1.150 + int i; 1.151 + ProducerParams producerParams[args->numProducers]; 1.152 + pthread_t producerThds[args->numProducers]; 1.153 + pthread_t consumerThd; 1.154 + 1.155 + ConsumerParams consumerParams; 1.156 + 1.157 + //Set up the param structs for producers.. gives them the mutex and cond var 1.158 + // to communicate with consumer 1.159 + //Also the core the producer should pin its thread to 1.160 + for(i=0; i < args->numProducers; i++) 1.161 + { 1.162 + producerParams[i].producerID = i + 1; //no ID of 0, a fact used in handshake 1.163 + producerParams[i].numTuplesToCreate = args->numTuplesToCreate; 1.164 + producerParams[i].coreID = i % NUM_CORES; 1.165 + } 1.166 + 1.167 + consumerParams.numProducers = args->numProducers; 1.168 + consumerParams.numTuplesToCreate = args->numTuplesToCreate; 1.169 + 1.170 + //take measurement before creation of threads, to get total exetime 1.171 + MeasStruct benchStartMeas, benchEndMeas; 1.172 + 1.173 + takeAMeas(0, benchStartMeas); 1.174 + 1.175 + for(i=0; i < args->numProducers; i++) 1.176 + { pthread_create( &producerThds[i], NULL, &producer_birthFn, (void*)&producerParams[i]); 1.177 + } 1.178 + 1.179 + pthread_create( &consumerThd, NULL, &consumer_birthFn, (void*)&consumerParams ); 1.180 + 1.181 + for(i=0; i<args->numProducers; i++) 1.182 + { pthread_join( producerThds[i], NULL ); 1.183 + } 1.184 + pthread_join( consumerThd, NULL ); 1.185 + 1.186 + //work is all done, so take a measurement snapshot at end 1.187 + takeAMeas(0, benchEndMeas); 1.188 + 1.189 + 1.190 +#ifdef MEASURE_PERF 1.191 + uint64_t totalExeCycles = ( benchEndMeas.cycles - benchStartMeas.cycles); 1.192 + printf("Total Execution: %lu\n", totalExeCycles); 1.193 +#else 1.194 + uint64_t totalExeCycles = ( benchEndMeas.total - benchStartMeas.total); 1.195 + printf("Total Cycles of Execution: %lu\n", totalExeCycles); 1.196 +#endif 1.197 + 1.198 + //====================================================== 1.199 + } 1.200 + 1.201 + 1.202 +/*This parsed the command line arguments and returns the values in a struct 1.203 + * Command line args should be a '-' followed by a single letter, then a value 1.204 + */ 1.205 +ParsedArgs * 1.206 +parse_arguments( int argc, char **argv ) 1.207 + { ParsedArgs *parsedArgs; 1.208 + int i; 1.209 + 1.210 + parsedArgs = malloc(sizeof(ParsedArgs)); 1.211 + if(argc < 2) 1.212 + { fprintf(stdout, "must give arguments"); 1.213 + fputs(usage, stdout); 1.214 + return EXIT_FAILURE; 1.215 + } 1.216 + for( i=1; i < argc; i++ ) 1.217 + { if(argv[i][0] == '-' && argv[i][2] == 0) 1.218 + { switch(argv[i][1]) 1.219 + { case 'p': 1.220 + { if(!isdigit(argv[++i][0])) 1.221 + { fprintf(stderr, "-p must be followed by the number of producer threads to spawn\n"); 1.222 + return EXIT_FAILURE; 1.223 + } 1.224 + parsedArgs->numProducers = atoi(argv[i]); 1.225 + if( parsedArgs->numProducers == 0 ) 1.226 + { fprintf(stderr, "invalid number of producers specified: %d\n", parsedArgs->numProducers); 1.227 + return EXIT_FAILURE; 1.228 + } 1.229 + else 1.230 + { DEBUG__printf1("num producers: %d\n", parsedArgs->numProducers ); 1.231 + } 1.232 + } 1.233 + break; 1.234 + case 't': 1.235 + { if( !isdigit( argv[++i][0] ) ) 1.236 + { fputs("-t must be followed by a number\n", stderr); 1.237 + return EXIT_FAILURE; 1.238 + } 1.239 + parsedArgs->numTuplesToCreate = atoi(argv[i]); 1.240 + DEBUG__printf1("num tuples to produce: %d\n", parsedArgs->numTuplesToCreate ); 1.241 + } 1.242 + break; 1.243 + case 'h': 1.244 + { fputs(usage, stdout); 1.245 + return 0; 1.246 + } 1.247 + default: 1.248 + { fprintf(stderr, "unrecognized argument: %s\n", argv[i]); 1.249 + fputs(usage, stderr); 1.250 + return EXIT_FAILURE; 1.251 + } 1.252 + } 1.253 + } 1.254 + else 1.255 + { fprintf(stdout, "unrecognized argument: %s\n", argv[i]); 1.256 + fputs(usage, stdout); 1.257 + return EXIT_FAILURE; 1.258 + } 1.259 + }//for 1.260 + return parsedArgs; 1.261 + } 1.262 + 1.263 +int main(int argc, char **argv) 1.264 + { ParsedArgs *args; 1.265 + int i; 1.266 + 1.267 + 1.268 + set_up_performance_counters(); 1.269 + 1.270 + init_stuff(); 1.271 + 1.272 + args = parse_arguments( argc, argv); 1.273 + 1.274 + if( args < 10 ) return args +1; //non-zero exit when parsing went wrong 1.275 + 1.276 + benchmark( args ); 1.277 + 1.278 + return 0; 1.279 + } 1.280 +
