ListNode* recursive_merge(vector<ListNode*>& lists, int left, int right) { if (left < right) { int mid = (left+right)/2; ListNode* l = recursive_merge(lists, left, mid); ListNode* r = recursive_merge(lists, mid+1, right); return merge(l, r); } else { return lists[left]; } }
int main(int argc, char ** argv) { int i; int ret; int hw_threads; int sw_threads; int running_threads; int buffer_size; int slice_size; unsigned int *data, *copy; timing_t t_start, t_stop; ms_t t_generate; ms_t t_sort; ms_t t_merge; ms_t t_check; if ((argc < 4) || (argc > 4)) { print_help(); exit(1); } // we have exactly 3 arguments now... hw_threads = atoi(argv[1]); sw_threads = atoi(argv[2]); // Base unit is bytes. Use macros TO_WORDS, TO_PAGES and TO_BLOCKS for conversion. buffer_size = atoi(argv[3])*PAGE_SIZE*PAGES_PER_THREAD; slice_size = PAGE_SIZE*PAGES_PER_THREAD; running_threads = hw_threads + sw_threads; //int gettimeofday(struct timeval *tv, struct timezone *tz); // init mailboxes mbox_init(&mb_start,TO_BLOCKS(buffer_size)); mbox_init(&mb_stop ,TO_BLOCKS(buffer_size)); // init reconos and communication resources reconos_init(14,15); res[0].type = RECONOS_TYPE_MBOX; res[0].ptr = &mb_start; res[1].type = RECONOS_TYPE_MBOX; res[1].ptr = &mb_stop; printf("Creating %i hw-threads: ", hw_threads); fflush(stdout); for (i = 0; i < hw_threads; i++) { printf(" %i",i); fflush(stdout); reconos_hwt_setresources(&(hwt[i]),res,2); reconos_hwt_create(&(hwt[i]),i,NULL); } printf("\n"); // init software threads printf("Creating %i sw-threads: ",sw_threads); fflush(stdout); for (i = 0; i < sw_threads; i++) { printf(" %i",i); fflush(stdout); pthread_attr_init(&swt_attr[i]); pthread_create(&swt[i], &swt_attr[i], sort_thread, (void*)res); } printf("\n"); //print_mmu_stats(); // create pages and generate data t_start = gettime(); printf("malloc page aligned ...\n"); data = malloc_page_aligned(TO_PAGES(buffer_size)); copy = malloc_page_aligned(TO_PAGES(buffer_size)); printf("generate data ...\n"); generate_data( data, TO_WORDS(buffer_size)); memcpy(copy,data,TO_WORDS(buffer_size)*4); t_stop = gettime(); t_generate = calc_timediff_ms(t_start,t_stop); // print data of first page printf("Printing of generated data skipped. \n"); //print_data(data, TO_WORDS(buffer_size)); // Start sort threads t_start = gettime(); printf("Putting %i blocks into job queue: ", TO_BLOCKS(buffer_size)); fflush(stdout); for (i=0; i<TO_BLOCKS(buffer_size); i++) { printf(" %i",i); fflush(stdout); mbox_put(&mb_start,(unsigned int)data+(i*BLOCK_SIZE)); } printf("\n"); // Wait for results printf("Waiting for %i acknowledgements: ", TO_BLOCKS(buffer_size)); fflush(stdout); for (i=0; i<TO_BLOCKS(buffer_size); i++) { printf(" %i",i); fflush(stdout); ret = mbox_get(&mb_stop); } printf("\n"); t_stop = gettime(); t_sort = calc_timediff_ms(t_start,t_stop); // merge data t_start = gettime(); printf("Merging sorted data slices...\n"); unsigned int * temp = malloc_page_aligned(TO_PAGES(buffer_size)); //printf("Data buffer at address %p \n", (void*)data); //printf("Address of temporary merge buffer: %p\n", (void*)temp); //printf("Total size of data in bytes: %i\n",buffer_size); //printf("Size of a sorting block in bytes: %i\n",BLOCK_SIZE); data = recursive_merge( data, temp, TO_WORDS(buffer_size), TO_WORDS(BLOCK_SIZE), simple_merge ); t_stop = gettime(); t_merge = calc_timediff_ms(t_start,t_stop); // check data //data[0] = 6666; // manual fault t_start = gettime(); printf("Checking sorted data: ... "); fflush(stdout); ret = check_data( data, copy, TO_WORDS(buffer_size)); if (ret >= 0) { printf("failure at word index %i\n", -ret); printf("expected 0x%08X found 0x%08X\n",copy[ret],data[ret]); printf("dumping the first 2048 words:\n"); for(i = 0; i < 2048; i++) { printf("%08X ",data[i]); if((i % 8) == 7) printf("\n"); } } else { printf("success\n"); //print_data(data, TO_WORDS(buffer_size)); } t_stop = gettime(); t_check = calc_timediff_ms(t_start,t_stop); // terminate all threads printf("Sending terminate message to %i threads:", running_threads); fflush(stdout); for (i=0; i<running_threads; i++) { printf(" %i",i); fflush(stdout); mbox_put(&mb_start,UINT_MAX); } printf("\n"); printf("Waiting for termination...\n"); for (i=0; i<hw_threads; i++) { pthread_join(hwt[i].delegate,NULL); } for (i=0; i<sw_threads; i++) { pthread_join(swt[i],NULL); } printf("\n"); print_mmu_stats(); printf( "Running times (size: %d words, %d hw-threads, %d sw-threads):\n" "\tGenerate data: %lu ms\n" "\tSort data : %lu ms\n" "\tMerge data : %lu ms\n" "\tCheck data : %lu ms\n" "Total computation time (sort & merge): %lu ms\n", TO_WORDS(buffer_size), hw_threads, sw_threads, t_generate, t_sort, t_merge, t_check, t_sort + t_merge ); //free(data); // Memory Leak on variable data!!! return 0; }
int main( int argc, char *argv[] ) { unsigned int i, start_count = 0, done_count = 0; timing_t t_start = 0, t_stop = 0, t_gen = 0, t_sort = 0, t_merge = 0, t_check = 0; unsigned int *addr; unsigned int dummy; int retval; printf( "-------------------------------------------------------\n" "ReconOS hardware multithreading case study (sort)\n" "(c) Computer Engineering Group, University of Paderborn\n\n" "eCos/POSIX, multi-threaded hardware version (" __FILE__ ")\n" "Compiled on " __DATE__ ", " __TIME__ ".\n" "-------------------------------------------------------\n\n" ); #ifdef USE_CACHE printf( "enabling data cache for external ram\n" ); XCache_EnableDCache( 0x80000000 ); #else printf( "data cache disabled\n" ); XCache_DisableDCache( ); #endif data = buf_a; //---------------------------------- //-- GENERATE DATA //---------------------------------- printf( "Generating data..." ); t_start = gettime( ); generate_data( data, SIZE ); t_stop = gettime( ); t_gen = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); #ifdef USE_CACHE // flush cache contents - the hardware can only read from main memory // TODO: storing could be more efficient printf( "Flushing cache..." ); XCache_EnableDCache( 0x80000000 ); printf( "done\n" ); #endif //---------------------------------- //-- SORT DATA //---------------------------------- // create mail boxes for 'start' and 'complete' messages mb_start_attr.mq_flags = mb_done_attr.mq_flags = 0; mb_start_attr.mq_maxmsg = mb_done_attr.mq_maxmsg = 10; mb_start_attr.mq_msgsize = mb_done_attr.mq_msgsize = 4; mb_start_attr.mq_curmsgs = mb_done_attr.mq_curmsgs = 0; // unlink mailboxes, if they exist retval = mq_unlink("/mb_start"); if (retval != 0 && errno != ENOENT) { // we don't care if it doesn't exist diag_printf("unable to unlink mb_start"); } retval = mq_unlink("/mb_done"); if (retval != 0 && errno != ENOENT) { // we don't care if it doesn't exist diag_printf("unable to unlink mb_done"); } // open/create mailboxes mb_start = mq_open("/mb_start", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, &mb_start_attr); if (mb_start == (mqd_t)-1) { diag_printf("unable to create mb_start"); } mb_done = mq_open("/mb_done", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, &mb_done_attr); if (mb_done == (mqd_t)-1) { diag_printf("unable to create mb_done"); } // create sorting sowftware threads for ( i = 0; i < MT_HW_NUM_SW_THREADS; i++ ) { pthread_attr_init(&thread_sorter_attr[i]); pthread_create(&thread_sorter[i], &thread_sorter_attr[i], sort8k_entry_posix, (void*)i); } // create sorting hardware thread pthread_attr_init(&hwthread_sorter_attr); pthread_attr_setstacksize(&hwthread_sorter_attr, STACK_SIZE); rthread_attr_init(&hwthread_sorter_hwattr); rthread_attr_setslotnum(&hwthread_sorter_hwattr, 0); rthread_attr_setresources(&hwthread_sorter_hwattr, hwthread_sorter_resources, 2); rthread_create(&hwthread_sorter, &hwthread_sorter_attr, &hwthread_sorter_hwattr, (void*)0); printf( "Sorting data..." ); i = 0; t_start = gettime( ); // put 9 messages into mb_start while ( start_count < 9 ) { addr = &data[i]; if ( mq_send( mb_start, ( void * ) &addr, sizeof(addr), 0 ) == 0 ) { start_count++; i += N; } else { perror("while sending to mq_send"); break; } } t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); while ( done_count < SIZE / N ) { t_start = gettime( ); // if we have something to distribute, // put one into the start mailbox if ( start_count < SIZE / N ) { addr = &data[i]; if ( mq_send( mb_start, ( void * ) &addr, sizeof(addr), 0 ) == 0 ) { start_count++; i += N; } else { perror("while sending to mq_send"); break; } } // see whether anybody's done if ( mq_receive( mb_done, (void*)&dummy, sizeof(dummy), 0 ) == sizeof(dummy) ) { done_count++; } else { perror( "while receiving from mq_done" ); break; } t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); } printf( "done\n" ); #ifdef USE_CACHE // flush cache contents // TODO: invalidating would suffice printf( "Flushing cache..." ); XCache_EnableDCache( 0x80000000 ); printf( "done\n" ); #endif //---------------------------------- //-- MERGE DATA //---------------------------------- printf( "Merging data..." ); t_start = gettime( ); data = recursive_merge( data, buf_b, SIZE, N, simple_merge ); t_stop = gettime( ); t_merge = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); //---------------------------------- //-- CHECK DATA //---------------------------------- printf( "Checking sorted data..." ); t_start = gettime( ); if ( check_data( data, SIZE ) != 0 ) printf( "CHECK FAILED!\n" ); else printf( "check successful.\n" ); t_stop = gettime( ); t_check = calc_timediff_ms( t_start, t_stop ); printf( "\nRunning times (size: %d words):\n" "\tGenerate data: %d ms\n" "\tSort data : %d ms\n" "\tMerge data : %d ms\n" "\tCheck data : %d ms\n" "\nTotal computation time (sort & merge): %d ms\n", SIZE, t_gen, t_sort, t_merge, t_check, t_sort + t_merge ); return 0; }
ListNode* mergeKLists(vector<ListNode*>& givenLists) { if (givenLists.size() == 0) return NULL; return recursive_merge(givenLists, 0, givenLists.size()-1); }
int main( int argc, char *argv[] ) { unsigned int i; hthread_time_t t_start = 0, t_stop = 0, t_gen = 0, t_sort = 0, t_merge = 0, t_check = 0; setup_cache(); printf( "-------------------------------------------------------\n" "ReconOS hardware multithreading case study (sort)\n" "(c) Computer Engineering Group, University of Paderborn\n\n" "eCos, single-threaded software version (" __FILE__ ")\n" "Compiled on " __DATE__ ", " __TIME__ ".\n" "-------------------------------------------------------\n\n" ); data = buf_a; //---------------------------------- //-- GENERATE DATA //---------------------------------- printf( "Generating data..." ); t_start = gettime( ); generate_data( data, SIZE ); t_stop = gettime( ); t_gen = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); //---------------------------------- //-- SORT DATA //---------------------------------- printf( "Sorting data..." ); for ( i = 0; i < SIZE; i += N ) { t_start = gettime( ); bubblesort( &data[i], N ); t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); } printf( "done\n" ); //---------------------------------- //-- MERGE DATA //---------------------------------- printf( "Merging data..." ); t_start = gettime( ); data = recursive_merge( data, buf_b, SIZE, N, simple_merge ); t_stop = gettime( ); t_merge = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); //---------------------------------- //-- CHECK DATA //---------------------------------- printf( "Checking sorted data..." ); t_start = gettime( ); if ( check_data( data, SIZE ) != 0 ) printf( "CHECK FAILED!\n" ); else printf( "check successful.\n" ); t_stop = gettime( ); t_check = calc_timediff_ms( t_start, t_stop ); printf( "\nRunning times (size: %lu words):\n" "\tGenerate data: %llu ms\n" "\tSort data : %llu ms\n" "\tMerge data : %llu ms\n" "\tCheck data : %llu ms\n" "\nTotal computation time (sort & merge): %llu ms\n", SIZE, t_gen, t_sort, t_merge, t_check, t_sort + t_merge ); return 0; }
int main( int argc, char *argv[] ) { unsigned int i, start_count = 0, done_count = 0, j; timing_t t_start = 0, t_stop = 0, t_gen = 0, t_sort = 0, t_merge = 0, t_check = 0, t_tmp; printf( "-------------------------------------------------------\n" "ReconOS hardware multithreading case study (sort)\n" "(c) Computer Engineering Group, University of Paderborn\n\n" "eCos, single-threaded hardware version (" __FILE__ ")\n" "Compiled on " __DATE__ ", " __TIME__ ".\n" "-------------------------------------------------------\n\n" ); #ifdef USE_CACHE printf( "enabling data cache for external ram\n" ); XCache_EnableDCache( 0x80000000 ); #else printf( "data cache disabled\n" ); XCache_DisableDCache( ); #endif data = buf_a; //---------------------------------- //-- GENERATE DATA //---------------------------------- printf( "Generating data..." ); t_start = gettime( ); generate_data( data, SIZE ); t_stop = gettime( ); t_gen = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); #ifdef USE_CACHE // flush cache contents - the hardware can only read from main memory // TODO: storing could be more efficient printf( "Flushing cache..." ); XCache_EnableDCache( 0x80000000 ); printf( "done\n" ); #endif //---------------------------------- //-- SORT DATA //---------------------------------- // create mail boxes for 'start' and 'complete' messages cyg_mbox_create( &mb_start_handle, &mb_start ); cyg_mbox_create( &mb_done_handle, &mb_done ); // create sorting thread reconos_hwthread_create( 16, // priority 0, // entry data (not needed) "MT_HW_SORT", // thread name hwthread_sorter_stack, // stack STACK_SIZE, // stack size &hwthread_sorter_handle, // thread handle &hwthread_sorter, // thread object (void*)UPBHWR_OSIF_0_BASEADDR, XPAR_OPB_INTC_0_OSIF_0_INTERRUPT_INTR+1, // ( void * ) XPAR_PLB_RECONOS_SLOT_0_BASEADDR, // base address // XPAR_OPB_INTC_0_PLB_RECONOS_SLOT_0_INTERRUPT_INTR + 1, // interrupt hwthread_sorter_resources, // resource array 2, // number of resources 0xFFFFFFFF, 0xFFFFFFFF ); cyg_thread_resume( hwthread_sorter_handle ); printf( "Sorting data..." ); i = 0; while ( done_count < SIZE / N ) { t_start = gettime( ); // if we have something to distribute, // put as many as possile into the start mailbox while ( start_count < SIZE / N ) { if ( cyg_mbox_tryput( mb_start_handle, ( void * ) &data[i] ) == true ) { start_count++; i += N; } else { // mailbox full break; } } t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); // see whether anybody's done t_start = gettime( ); if ( ( t_tmp = ( timing_t ) cyg_mbox_get( mb_done_handle ) ) != 0 ) { done_count++; } else { printf( "cyg_mbox_get returned NULL!\n" ); } t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); } printf( "done\n" ); #ifdef USE_CACHE // flush cache contents // TODO: invalidating would suffice printf( "Flushing cache..." ); XCache_EnableDCache( 0x80000000 ); printf( "done\n" ); #endif //---------------------------------- //-- MERGE DATA //---------------------------------- printf( "Merging data..." ); t_start = gettime( ); data = recursive_merge( data, buf_b, SIZE, N, simple_merge ); t_stop = gettime( ); t_merge = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); //---------------------------------- //-- CHECK DATA //---------------------------------- printf( "Checking sorted data..." ); t_start = gettime( ); if ( check_data( data, SIZE ) != 0 ) printf( "CHECK FAILED!\n" ); else printf( "check successful.\n" ); t_stop = gettime( ); t_check = calc_timediff_ms( t_start, t_stop ); printf( "\nRunning times (size: %d words):\n" "\tGenerate data: %d ms\n" "\tSort data : %d ms\n" "\tMerge data : %d ms\n" "\tCheck data : %d ms\n" "\nTotal computation time (sort & merge): %d ms\n", SIZE, t_gen, t_sort, t_merge, t_check, t_sort + t_merge ); return 0; }
void main() { unsigned int i; timing_t t_start = 0, t_stop = 0, t_gen = 0, t_sort = 0, t_merge = 0, t_check = 0; printf( "-------------------------------------------------------\n" "ReconOS hardware multithreading case study (sort)\n" "(c) Computer Engineering Group, University of Paderborn\n\n" "eCos/POSIX, single-threaded software version (" __FILE__ ")\n" "Compiled on " __DATE__ ", " __TIME__ ".\n" "-------------------------------------------------------\n\n" ); #ifdef USE_CACHE diag_printf( "enabling data cache for external ram\n" ); //XCache_EnableDCache( 0x80000000 ); HAL_DCACHE_ENABLE(); #else diag_printf( "data cache disabled\n" ); //XCache_DisableDCache( ); HAL_DCACHE_DISABLE(); #endif data = buf_a; //---------------------------------- //-- GENERATE DATA //---------------------------------- printf( "Generating data..." ); t_start = gettime( ); generate_data( data, SIZE ); t_stop = gettime( ); t_gen = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); //---------------------------------- //-- SORT DATA //---------------------------------- printf( "Sorting data..." ); for ( i = 0; i < SIZE; i += N ) { t_start = gettime( ); bubblesort( &data[i], N ); t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); } printf( "done\n" ); //---------------------------------- //-- MERGE DATA //---------------------------------- printf( "Merging data..." ); t_start = gettime( ); data = recursive_merge( data, buf_b, SIZE, N, simple_merge ); t_stop = gettime( ); t_merge = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); //---------------------------------- //-- CHECK DATA //---------------------------------- printf( "Checking sorted data..." ); t_start = gettime( ); if ( check_data( data, SIZE ) != 0 ) printf( "CHECK FAILED!\n" ); else printf( "check successful.\n" ); t_stop = gettime( ); t_check = calc_timediff_ms( t_start, t_stop ); printf( "\nRunning times (size: %d words):\n" "\tGenerate data: %d ms\n" "\tSort data : %d ms\n" "\tMerge data : %d ms\n" "\tCheck data : %d ms\n" "\nTotal computation time (sort & merge): %d ms\n", SIZE, t_gen, t_sort, t_merge, t_check, t_sort + t_merge ); }