/* ============================================================================= * main * ============================================================================= */ MAIN(argc, argv) { char exitmsg[1024]; GOTO_REAL(); load_syncchar_map("sync_char.map.yada"); /* * Initialization */ parseArgs(argc, (char** const)argv); sprintf(exitmsg, "END BENCHMARK %s-parallel-phase\n", argv[0]); SIM_GET_NUM_CPU(global_numThread); TM_STARTUP(global_numThread); P_MEMORY_STARTUP(global_numThread); thread_startup(global_numThread); global_meshPtr = mesh_alloc(); assert(global_meshPtr); printf("Angle constraint = %lf\n", global_angleConstraint); printf("Reading input... "); long initNumElement = mesh_read(global_meshPtr, global_inputPrefix); puts("done."); global_workHeapPtr = heap_alloc(1, &element_heapCompare); assert(global_workHeapPtr); long initNumBadElement = initializeWork(global_workHeapPtr, global_meshPtr); printf("Initial number of mesh elements = %li\n", initNumElement); printf("Initial number of bad elements = %li\n", initNumBadElement); printf("Starting triangulation..."); fflush(stdout); /* * Run benchmark */ TIMER_T start; TIMER_READ(start); OSA_PRINT("entering parallel phase\n",0); START_INSTRUMENTATION(); GOTO_SIM(); #ifdef OTM #pragma omp parallel { process(); } #else thread_start(process, NULL); #endif GOTO_REAL(); OSA_PRINT("exiting parallel phase\n",0); OSA_PRINT(exitmsg,0); STOP_INSTRUMENTATION(); TIMER_T stop; TIMER_READ(stop) puts(" done."); printf("Elapsed time = %0.3lf\n", TIMER_DIFF_SECONDS(start, stop)); fflush(stdout); /* * Check solution */ long finalNumElement = initNumElement + global_totalNumAdded; printf("Final mesh size = %li\n", finalNumElement); printf("Number of elements processed = %li\n", global_numProcess); fflush(stdout); #if 0 bool_t isSuccess = mesh_check(global_meshPtr, finalNumElement); #else bool_t isSuccess = TRUE; #endif printf("Final mesh is %s\n", (isSuccess ? "valid." : "INVALID!")); fflush(stdout); assert(isSuccess); /* * TODO: deallocate mesh and work heap */ TM_SHUTDOWN(); P_MEMORY_SHUTDOWN(); GOTO_SIM(); thread_shutdown(); MAIN_RETURN(0); }
/** * thread_proc() * thread function executing * parallel increment of a shared counter. */ int krbtree_thread_proc(void * data) { #if defined (KTHCBM_VERBOSE) int nstnum = (int) data; #endif int done = 0; int my_share = gnTargetValue / gnThreadCount; int nFinishNumber = 0; unsigned int randval1, randval2; char buf[OSA_OUTBUF_SIZE]; krbtree_modulate_prio(); down( &scsembarrier ); gnAwakeCount++; // Reset the stats when the last process is ready to go if(gnAwakeCount == gnThreadCount){ OSA_MAGIC(OSA_CLEAR_STAT); } up( &scsembarrier ); #ifdef KTHCBM_VERBOSE printk( KERN_ERR "Awaiting sync for shared counter thread %d\n", nstnum ); #endif while( gnAwakeCount < gnThreadCount ) { msleep(KTHCBM_BACKOFF_WAIT); } #ifdef KTHCBM_VERBOSE printk( KERN_ERR "Barrier crossed shared counter kthread #%d\n", nstnum ); #endif while( !kthread_should_stop() && !done ) { // Work goes here randval1 = (unsigned int) (max_val * (get_osa_random()%RMAX) / (RMAX + 1)); randval2 = (unsigned int) (100 * (get_osa_random()%RMAX) / (RMAX + 1)); if(randval2 > insert_delete_balance){ remove(randval1); } else { insert(randval1); } done = !--my_share; // yield after roughly every 30 iterations // This number was picked because we are trying to use a window of // 1024 and 32 threads. 1024/32 = 32, 30 gives us some wiggle // room if(done % 30 == 0){ yield(); } if( done ) { down( &semdone ); nFinishNumber = ++gnThreadsComplete; up( &semdone ); // Stop the stats as soon as we are finished - avoid counting // tear down costs if(gnThreadsComplete >= gnThreadCount){ snprintf(buf, OSA_OUTBUF_SIZE, "rbtree microbenchmark: %lu threads performing %lu ops, %d deletes", gnThreadCount, gnTargetValue, successful_deletes); OSA_PRINT(buf, strlen(buf)); OSA_MAGIC(OSA_OUTPUT_STAT); } } } #ifdef KTHCBM_VERBOSE printk(KERN_ERR "Thread %d finished\n", nstnum); #endif while( !kthread_should_stop() ) schedule_timeout_uninterruptible(1); return 0; }