static void *worker_thread_entry(void *param) { work_thread_info *thread = (work_thread_info *)param; osd_work_queue *queue = thread->queue; // loop until we exit for ( ;; ) { // block waiting for work or exit // bail on exit, and only wait if there are no pending items in queue if (!queue->exiting && queue->list == NULL) { begin_timing(thread->waittime); osd_event_wait(thread->wakeevent, INFINITE); end_timing(thread->waittime); } if (queue->exiting) break; // indicate that we are live atomic_exchange32(&thread->active, TRUE); atomic_increment32(&queue->livethreads); // process work items for ( ;; ) { osd_ticks_t stopspin; // process as much as we can worker_thread_process(queue, thread); // if we're a high frequency queue, spin for a while before giving up if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list == NULL) { // spin for a while looking for more work begin_timing(thread->spintime); stopspin = osd_ticks() + SPIN_LOOP_TIME; do { int spin = 10000; while (--spin && queue->list == NULL) osd_yield_processor(); } while (queue->list == NULL && osd_ticks() < stopspin); end_timing(thread->spintime); } // if nothing more, release the processor if (queue->list == NULL) break; add_to_stat(&queue->spinloops, 1); } // decrement the live thread count atomic_exchange32(&thread->active, FALSE); atomic_decrement32(&queue->livethreads); } return NULL; }
static unsigned __stdcall worker_thread_entry(void *param) { work_thread_info *thread = param; osd_work_queue *queue = thread->queue; // loop until we exit for ( ;; ) { // block waiting for work or exit DWORD result = WAIT_OBJECT_0; // bail on exit, and only wait if there are no pending items in queue if (!queue->exiting && queue->list == NULL) { begin_timing(thread->waittime); result = WaitForSingleObject(thread->wakeevent, INFINITE); end_timing(thread->waittime); } if (queue->exiting) break; // indicate that we are live interlocked_exchange32(&thread->active, TRUE); interlocked_increment(&queue->livethreads); // process work items for ( ;; ) { osd_ticks_t stopspin; // process as much as we can worker_thread_process(queue, thread); // if we're a high frequency queue, spin for a while before giving up if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ) { // spin for a while looking for more work begin_timing(thread->spintime); stopspin = osd_ticks() + SPIN_LOOP_TIME; while (queue->list == NULL && osd_ticks() < stopspin) YieldProcessor(); end_timing(thread->spintime); } // if nothing more, release the processor if (queue->list == NULL) break; add_to_stat(&queue->spinloops, 1); } // decrement the live thread count interlocked_exchange32(&thread->active, FALSE); interlocked_decrement(&queue->livethreads); } return 0; }
static void *worker_thread_entry(void *param) { work_thread_info *thread = (work_thread_info *)param; osd_work_queue &queue = thread->queue; // loop until we exit for ( ;; ) { // block waiting for work or exit // bail on exit, and only wait if there are no pending items in queue if (queue.exiting) break; if (!queue_has_list_items(&queue)) { begin_timing(thread->waittime); thread->wakeevent.wait( OSD_EVENT_WAIT_INFINITE); end_timing(thread->waittime); } if (queue.exiting) break; // indicate that we are live thread->active = TRUE; ++queue.livethreads; // process work items for ( ;; ) { // process as much as we can worker_thread_process(&queue, thread); // if we're a high frequency queue, spin for a while before giving up if (queue.flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue.list.load() == nullptr) { // spin for a while looking for more work begin_timing(thread->spintime); spin_while<std::atomic<osd_work_item *>, osd_work_item *>(&queue.list, (osd_work_item *)nullptr, SPIN_LOOP_TIME); end_timing(thread->spintime); } // if nothing more, release the processor if (!queue_has_list_items(&queue)) break; add_to_stat(queue.spinloops, 1); } // decrement the live thread count thread->active = FALSE; --queue.livethreads; } return nullptr; }
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout) { // if no threads, no waiting if (queue->threads == 0) return TRUE; // if no items, we're done if (queue->items == 0) return TRUE; // if this is a multi queue, help out rather than doing nothing if (queue->flags & WORK_QUEUE_FLAG_MULTI) { work_thread_info *thread = &queue->thread[queue->threads]; end_timing(thread->waittime); // process what we can as a worker thread worker_thread_process(queue, thread); // if we're a high frequency queue, spin until done if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->items != 0) { osd_ticks_t stopspin = osd_ticks() + timeout; // spin until we're done begin_timing(thread->spintime); do { int spin = 10000; while (--spin && queue->items != 0) osd_yield_processor(); } while (queue->items != 0 && osd_ticks() < stopspin); end_timing(thread->spintime); begin_timing(thread->waittime); return (queue->items == 0); } begin_timing(thread->waittime); } // reset our done event and double-check the items before waiting osd_event_reset(queue->doneevent); atomic_exchange32(&queue->waiting, TRUE); if (queue->items != 0) osd_event_wait(queue->doneevent, timeout); atomic_exchange32(&queue->waiting, FALSE); // return TRUE if we actually hit 0 return (queue->items == 0); }
int main(int argc, char *argv[]) { struct timespec timing; int i, round; void *m[ALLOCS]; /* a random set of allocations we test */ int sizes[16] = { 1, 13, 100, 1000, 16, 10000, 50, 17, 123, 32, 8, 64, 8096, 1024, 123, 9 }; library_init(NULL, "malloc_speed"); atexit(library_deinit); print_mallinfo(); start_timing(&timing); for (round = 0; round < ROUNDS; round++) { for (i = 0; i < ALLOCS; i++) { m[i] = malloc(sizes[(round + i) % countof(sizes)]); } for (i = 0; i < ALLOCS; i++) { free(m[i]); } } printf("time for %d malloc/frees, repeating %d rounds: %.4fs\n", ALLOCS, ROUNDS, end_timing(&timing)); print_mallinfo(); return 0; }
int main(int argc, char** argv) { double* S = malloc_aligned<double>(LENGTH, 5); double* X = malloc_aligned<double>(LENGTH, 5); double* T = malloc_aligned<double>(LENGTH, 5); double* r = malloc_aligned<double>(LENGTH, 5); double* v = malloc_aligned<double>(LENGTH, 5); for(int i = 0; i < LENGTH; i++) { S[i] = 100; X[i] = 98; T[i] = 2; r[i] = 0.02; v[i] = 5; } start_timing(); double sum = 0; for(int i = 0; i < ROUNDS; i++) { sum += run(S, X, T, r, v); } printf("%f \t(%f)\n", end_timing(), sum / (LENGTH * ROUNDS)); return 0; }
static void run_test(diffie_hellman_group_t group, int rounds) { diffie_hellman_t *l[rounds], *r; chunk_t chunk; struct timespec timing; int round; r = lib->crypto->create_dh(lib->crypto, group); if (!r) { printf("skipping %N, not supported\n", diffie_hellman_group_names, group); return; } printf("%N:\t", diffie_hellman_group_names, group); start_timing(&timing); for (round = 0; round < rounds; round++) { l[round] = lib->crypto->create_dh(lib->crypto, group); } printf("A = g^a/s: %8.1f", rounds / end_timing(&timing)); for (round = 0; round < rounds; round++) { l[round]->get_my_public_value(l[round], &chunk); r->set_other_public_value(r, chunk); chunk_free(&chunk); } r->get_my_public_value(r, &chunk); start_timing(&timing); for (round = 0; round < rounds; round++) { l[round]->set_other_public_value(l[round], chunk); } printf(" | S = B^a/s: %8.1f\n", rounds / end_timing(&timing)); chunk_free(&chunk); for (round = 0; round < rounds; round++) { l[round]->destroy(l[round]); } r->destroy(r); }
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout) { // if no threads, no waiting if (queue->threads == 0) return TRUE; // if no items, we're done if (queue->items == 0) return TRUE; // if this is a multi queue, help out rather than doing nothing if (queue->flags & WORK_QUEUE_FLAG_MULTI) { work_thread_info *thread = &queue->thread[queue->threads]; osd_ticks_t stopspin = osd_ticks() + timeout; end_timing(thread->waittime); // process what we can as a worker thread worker_thread_process(queue, thread); // if we're a high frequency queue, spin until done if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ) { // spin until we're done begin_timing(thread->spintime); while (queue->items != 0 && osd_ticks() < stopspin) YieldProcessor(); end_timing(thread->spintime); begin_timing(thread->waittime); return (queue->items == 0); } begin_timing(thread->waittime); } // reset our done event and double-check the items before waiting ResetEvent(queue->doneevent); interlocked_exchange32(&queue->waiting, TRUE); if (queue->items != 0) WaitForSingleObject(queue->doneevent, timeout * 1000 / osd_ticks_per_second()); interlocked_exchange32(&queue->waiting, FALSE); // return TRUE if we actually hit 0 return (queue->items == 0); }
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout) { // if no threads, no waiting if (queue->threads == 0) return TRUE; // if no items, we're done if (queue->items == 0) return TRUE; // if this is a multi queue, help out rather than doing nothing if (queue->flags & WORK_QUEUE_FLAG_MULTI) { work_thread_info *thread = queue->thread[queue->threads]; end_timing(thread->waittime); // process what we can as a worker thread worker_thread_process(queue, thread); // if we're a high frequency queue, spin until done if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->items != 0) { // spin until we're done begin_timing(thread->spintime); spin_while_not<std::atomic<int>,int>(&queue->items, 0, timeout); end_timing(thread->spintime); begin_timing(thread->waittime); return (queue->items == 0); } begin_timing(thread->waittime); } // reset our done event and double-check the items before waiting queue->doneevent.reset(); queue->waiting = TRUE; if (queue->items != 0) queue->doneevent.wait(timeout); queue->waiting = FALSE; // return TRUE if we actually hit 0 return (queue->items == 0); }
ATTR_HOT inline void netlist_net_t::update_dev(const netlist_core_terminal_t *inp, const UINT32 mask) const { if ((inp->state() & mask) != 0) { netlist_core_device_t &netdev = inp->netdev(); begin_timing(netdev.total_time); inc_stat(netdev.stat_count); netdev.update_dev(); end_timing(netdev().total_time); } }
void osd_work_queue_free(osd_work_queue *queue) { // if we have threads, clean them up if (queue->threads > 0 && queue->thread != NULL) { int threadnum; // stop the timer for "waittime" on the main thread end_timing(queue->thread[queue->threads].waittime); // signal all the threads to exit queue->exiting = TRUE; for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; if (thread->wakeevent != NULL) SetEvent(thread->wakeevent); } // wait for all the threads to go away for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; // block on the thread going away, then close the handle if (thread->handle != NULL) { WaitForSingleObject(thread->handle, INFINITE); CloseHandle(thread->handle); } // clean up the wake event if (thread->wakeevent != NULL) CloseHandle(thread->wakeevent); } #if KEEP_STATISTICS // output per-thread statistics for (threadnum = 0; threadnum <= queue->threads; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime; printf("Thread %d: items=%9d run=%5.2f%% (%5.2f%%) spin=%5.2f%% wait/other=%5.2f%%\n", threadnum, thread->itemsdone, (double)thread->runtime * 100.0 / (double)total, (double)thread->actruntime * 100.0 / (double)total, (double)thread->spintime * 100.0 / (double)total, (double)thread->waittime * 100.0 / (double)total); } #endif } // free the list if (queue->thread != NULL) free(queue->thread); // free all the events if (queue->doneevent != NULL) CloseHandle(queue->doneevent); // free all items in the free list while (queue->free != NULL) { osd_work_item *item = (osd_work_item *)queue->free; queue->free = item->next; if (item->event != NULL) CloseHandle(item->event); free(item); } // free all items in the active list while (queue->list != NULL) { osd_work_item *item = (osd_work_item *)queue->list; queue->list = item->next; if (item->event != NULL) CloseHandle(item->event); free(item); } #if KEEP_STATISTICS printf("Items queued = %9d\n", queue->itemsqueued); printf("SetEvent calls = %9d\n", queue->setevents); printf("Extra items = %9d\n", queue->extraitems); printf("Spin loops = %9d\n", queue->spinloops); #endif // free the queue itself free(queue); }
static void *worker_thread_entry(void *param) { work_thread_info *thread = (work_thread_info *)param; osd_work_queue *queue = thread->queue; #if defined(SDLMAME_MACOSX) void *arp = NewAutoreleasePool(); #endif // loop until we exit for ( ;; ) { // block waiting for work or exit // bail on exit, and only wait if there are no pending items in queue if (queue->exiting) break; if (!queue_has_list_items(queue)) { begin_timing(thread->waittime); osd_event_wait(thread->wakeevent, OSD_EVENT_WAIT_INFINITE); end_timing(thread->waittime); } if (queue->exiting) break; // indicate that we are live atomic_exchange32(&thread->active, TRUE); atomic_increment32(&queue->livethreads); // process work items for ( ;; ) { // process as much as we can worker_thread_process(queue, thread); // if we're a high frequency queue, spin for a while before giving up if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list == NULL) { // spin for a while looking for more work begin_timing(thread->spintime); spin_while(&queue->list, (osd_work_item *)NULL, SPIN_LOOP_TIME); end_timing(thread->spintime); } // if nothing more, release the processor if (!queue_has_list_items(queue)) break; add_to_stat(&queue->spinloops, 1); } // decrement the live thread count atomic_exchange32(&thread->active, FALSE); atomic_decrement32(&queue->livethreads); } #if defined(SDLMAME_MACOSX) ReleaseAutoreleasePool(arp); #endif return NULL; }
osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_callback callback, INT32 numitems, void *parambase, INT32 paramstep, UINT32 flags) { osd_work_item *itemlist = nullptr, *lastitem = nullptr; osd_work_item **item_tailptr = &itemlist; int itemnum; // loop over items, building up a local list of work for (itemnum = 0; itemnum < numitems; itemnum++) { osd_work_item *item; // first allocate a new work item; try the free list first { std::lock_guard<std::mutex> lock(queue->lock); do { item = (osd_work_item *)queue->free; } while (item != nullptr && !queue->free.compare_exchange_weak(item, item->next, std::memory_order_release, std::memory_order_relaxed)); } // if nothing, allocate something new if (item == nullptr) { // allocate the item item = new osd_work_item(*queue); if (item == nullptr) return nullptr; } else { item->done = FALSE; // needs to be set this way to prevent data race/usage of uninitialized memory on Linux } // fill in the basics item->next = nullptr; item->callback = callback; item->param = parambase; item->result = nullptr; item->flags = flags; // advance to the next lastitem = item; *item_tailptr = item; item_tailptr = &item->next; parambase = (UINT8 *)parambase + paramstep; } // enqueue the whole thing within the critical section { std::lock_guard<std::mutex> lock(queue->lock); *queue->tailptr = itemlist; queue->tailptr = item_tailptr; } // increment the number of items in the queue queue->items += numitems; add_to_stat(queue->itemsqueued, numitems); // look for free threads to do the work if (queue->livethreads < queue->threads) { int threadnum; // iterate over all the threads for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = queue->thread[threadnum]; // if this thread is not active, wake him up if (!thread->active) { thread->wakeevent.set(); add_to_stat(queue->setevents, 1); // for non-shared, the first one we find is good enough if (--numitems == 0) break; } } } // if no threads, run the queue now on this thread if (queue->threads == 0) { end_timing(queue->thread[0]->waittime); worker_thread_process(queue, queue->thread[0]); begin_timing(queue->thread[0]->waittime); } // only return the item if it won't get released automatically return (flags & WORK_ITEM_FLAG_AUTO_RELEASE) ? nullptr : lastitem; }
void osd_work_queue_free(osd_work_queue *queue) { // stop the timer for "waittime" on the main thread if (queue->flags & WORK_QUEUE_FLAG_MULTI) { end_timing(queue->thread[queue->threads]->waittime); } // signal all the threads to exit queue->exiting = TRUE; for (int threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = queue->thread[threadnum]; thread->wakeevent.set(); } // wait for all the threads to go away for (int threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = queue->thread[threadnum]; // block on the thread going away, then close the handle if (thread->handle != nullptr) { thread->handle->join(); delete thread->handle; } } #if KEEP_STATISTICS // output per-thread statistics for (work_thread_info *thread : queue->thread) { osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime; printf("Thread %d: items=%9d run=%5.2f%% (%5.2f%%) spin=%5.2f%% wait/other=%5.2f%% total=%9d\n", thread->id, thread->itemsdone, (double)thread->runtime * 100.0 / (double)total, (double)thread->actruntime * 100.0 / (double)total, (double)thread->spintime * 100.0 / (double)total, (double)thread->waittime * 100.0 / (double)total, (UINT32) total); } #endif // free the list for (auto & th : queue->thread) delete th; queue->thread.clear(); // free all items in the free list while (queue->free.load() != nullptr) { osd_work_item *item = (osd_work_item *)queue->free; queue->free = item->next; if (item->event != nullptr) delete item->event; delete item; } // free all items in the active list while (queue->list.load() != nullptr) { osd_work_item *item = (osd_work_item *)queue->list; queue->list = item->next; if (item->event != nullptr) delete item->event; delete item; } #if KEEP_STATISTICS printf("Items queued = %9d\n", queue->itemsqueued.load()); printf("SetEvent calls = %9d\n", queue->setevents.load()); printf("Extra items = %9d\n", queue->extraitems.load()); printf("Spin loops = %9d\n", queue->spinloops.load()); #endif // free the queue itself delete queue; }
int main( int argc , char *argv[] ) { /* index counters */ int i ; /* Command line options */ char *output_file_name ; char *static_file_name ; char *mobile_file_name ; int global_grid_size ; int angle_step ; float surface ; float internal_value ; int electrostatics ; int keep_per_rotation ; int kept_scores ; int rescue ; int calculate ; float reverse_calculated_one_span ; char *default_global_grid_size ; char *default_angle_step ; char *default_surface ; char *default_internal_value ; char *default_electrostatics ; char *default_keep_per_rotation ; /* File stuff */ FILE *ftdock_file ; char line_buffer[100] ; int id , id2 , SCscore ; float RPscore ; int x , y , z , z_twist , theta , phi ; /* Angles stuff */ struct Angle Angles ; int first_rotation , rotation ; /* Structures */ struct Structure Static_Structure , Mobile_Structure ; struct Structure Origin_Static_Structure , Origin_Mobile_Structure ; struct Structure Rotated_at_Origin_Mobile_Structure ; /* Co-ordinates */ int xyz , fx , fy , fz , fxyz ; /* Grid stuff */ float grid_span , one_span ; float *static_grid ; float *mobile_grid ; float *convoluted_grid ; float *static_elec_grid = ( void * ) 0 ; float *mobile_elec_grid = ( void * ) 0 ; float *convoluted_elec_grid = ( void * ) 0 ; /* FFTW stuff */ fftwf_plan plan_static_grid, plan_static_elec_grid, plan_multiple_fsg, plan_multiple_elec_fsg, plan_mobile_grid, plan_mobile_elec_grid; fftwf_complex *static_fsg ; fftwf_complex *mobile_fsg ; fftwf_complex *multiple_fsg ; fftwf_complex *static_elec_fsg = ( void * ) 0 ; fftwf_complex *mobile_elec_fsg = ( void * ) 0 ; fftwf_complex *multiple_elec_fsg = ( void * ) 0 ; /* Scores */ struct Score *Scores ; float max_es_value ; /************/ /* Its nice to tell people what going on straight away */ setvbuf( stdout , (char *)NULL , _IONBF , 0 ) ; printf( "\n 3D-Dock Suite (March 2001)\n" ) ; printf( " Copyright (C) 1997-2000 Gidon Moont\n" ) ; printf( " This program comes with ABSOLUTELY NO WARRANTY\n" ) ; printf( " for details see license. This program is free software,\n"); printf( " and you may redistribute it under certain conditions.\n\n"); printf( " Biomolecular Modelling Laboratory\n" ) ; printf( " Imperial Cancer Research Fund\n" ) ; printf( " 44 Lincoln's Inn Fields\n" ) ; printf( " London WC2A 3PX\n" ) ; printf( " +44 (0)20 7269 3348\n" ) ; printf( " http://www.bmm.icnet.uk/\n\n" ) ; printf( "Starting FTDock (v2.0) global search program\n" ) ; /************/ /* Memory allocation */ if( ( ( output_file_name = ( char * ) fftwf_malloc ( 500 * sizeof( char ) ) ) == NULL ) || ( ( static_file_name = ( char * ) fftwf_malloc ( 500 * sizeof( char ) ) ) == NULL ) || ( ( mobile_file_name = ( char * ) fftwf_malloc ( 500 * sizeof( char ) ) ) == NULL ) ) { GENERAL_MEMORY_PROBLEM } /************/ /* Command Line defaults */ strcpy( output_file_name , "ftdock_global.dat" ) ; strcpy( static_file_name , " --static file name was not provided--" ) ; strcpy( mobile_file_name , " --mobile file name was not provided--" ) ; global_grid_size = 128 ; angle_step = 12 ; surface = 1.3 ; internal_value = -15 ; electrostatics = 1 ; keep_per_rotation = 3 ; rescue = 0 ; calculate = 1 ; reverse_calculated_one_span = 0.7 ; default_global_grid_size = "(default calculated)" ; default_angle_step = "(default)" ; default_surface = "(default)" ; default_internal_value = "(default)" ; default_electrostatics = "(default)" ; default_keep_per_rotation = "(default)" ; /* Command Line parse */ for( i = 1 ; i < argc ; i ++ ) { if( strcmp( argv[i] , "-out" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } strcpy( output_file_name , argv[i] ) ; } else { if( strcmp( argv[i] , "-static" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } strcpy( static_file_name , argv[i] ) ; } else { if( strcmp( argv[i] , "-mobile" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } strcpy( mobile_file_name , argv[i] ) ; } else { if( strcmp( argv[i] , "-grid" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } sscanf( argv[i] , "%d" , &global_grid_size ) ; if( ( global_grid_size % 2 ) != 0 ) { printf( "Grid size must be even\n" ) ; exit( EXIT_FAILURE ) ; } default_global_grid_size = "(user defined)" ; calculate = 0 ; } else { if( strcmp( argv[i] , "-angle_step" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } sscanf( argv[i] , "%d" , &angle_step ) ; default_angle_step = "(user defined)" ; } else { if( strcmp( argv[i] , "-surface" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } sscanf( argv[i] , "%f" , &surface ) ; default_surface = "(user defined)" ; } else { if( strcmp( argv[i] , "-internal" ) == 0 ) { i ++ ; if( i == argc ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } sscanf( argv[i] , "%f" , &internal_value ) ; default_internal_value = "(user defined)" ; } else { if( strcmp( argv[i] , "-noelec" ) == 0 ) { electrostatics = 0 ; default_electrostatics = "(user defined)" ; } else { if( strcmp( argv[i] , "-keep" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } sscanf( argv[i] , "%d" , &keep_per_rotation ) ; default_keep_per_rotation = "(user defined)" ; } else { if( strcmp( argv[i] , "-rescue" ) == 0 ) { rescue = 1 ; } else { if( strcmp( argv[i] , "-calculate_grid" ) == 0 ) { i ++ ; if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } calculate = 1 ; default_global_grid_size = "(user defined calculated)" ; sscanf( argv[i] , "%f" , &reverse_calculated_one_span ) ; } else { printf( "Bad command line\n" ) ; exit( EXIT_FAILURE ) ; } } } } } } } } } } } } /************/ /* Rescue option */ if( rescue == 1 ) { printf( "RESCUE mode\n" ) ; if( ( ftdock_file = fopen( "scratch_parameters.dat" , "r" ) ) == NULL ) { printf( "Could not open scratch_parameters.dat for reading.\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } calculate = 0 ; default_global_grid_size = "(read from rescue file)" ; default_angle_step = "(read from rescue file)" ; default_surface = "(read from rescue file)" ; default_internal_value = "(read from rescue file)" ; default_electrostatics = "(read from rescue file)" ; while( fgets( line_buffer , 99 , ftdock_file ) ) { if( strncmp( line_buffer , "Static molecule" , 15 ) == 0 ) sscanf( line_buffer , "Static molecule :: %s" , static_file_name ) ; if( strncmp( line_buffer , "Mobile molecule" , 15 ) == 0 ) sscanf( line_buffer , "Mobile molecule :: %s" , mobile_file_name ) ; if( strncmp( line_buffer , "Output file name" , 16 ) == 0 ) sscanf( line_buffer , "Output file name :: %s" , output_file_name ) ; if( strncmp( line_buffer , "Global grid size" , 16 ) == 0 ) sscanf( line_buffer , "Global grid size :: %d" , &global_grid_size ) ; if( strncmp( line_buffer , "Global search angle step" , 24 ) == 0 ) sscanf( line_buffer , "Global search angle step :: %d" , &angle_step ) ; if( strncmp( line_buffer , "Global surface thickness" , 24 ) == 0 ) sscanf( line_buffer , "Global surface thickness :: %f" , &surface ) ; if( strncmp( line_buffer , "Global internal deterrent value" , 31 ) == 0 ) sscanf( line_buffer , "Global internal deterrent value :: %f" , &internal_value ) ; if( strncmp( line_buffer , "Electrostatics :: on" , 44 ) == 0 ) electrostatics = 1 ; if( strncmp( line_buffer , "Electrostatics :: off" , 44 ) == 0 ) electrostatics = 0 ; if( strncmp( line_buffer , "Global keep per rotation" , 25 ) == 0 ) sscanf( line_buffer , "Global keep per rotation :: %d" , &keep_per_rotation ) ; } fclose( ftdock_file ) ; if( ( ftdock_file = fopen( "scratch_scores.dat" , "r" ) ) == NULL ) { printf( "Could not open scratch_scores.dat for reading.\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } fgets( line_buffer , 99 , ftdock_file ) ; while( fgets( line_buffer , 99 , ftdock_file ) ) { sscanf( line_buffer , "G_DATA %d " , &first_rotation ) ; } fclose( ftdock_file ) ; first_rotation ++ ; printf( "Will be starting from rotation %d\n" , first_rotation ) ; /************/ } else { first_rotation = 1 ; } /************/ /* Do these things first so that bad inputs will be caught soonest */ /* Read in Structures from pdb files */ Static_Structure = read_pdb_to_structure( static_file_name ) ; Mobile_Structure = read_pdb_to_structure( mobile_file_name ) ; if( Mobile_Structure.length > Static_Structure.length ) { printf( "WARNING\n" ) ; printf( "The mobile molecule has more residues than the static\n" ) ; printf( "Are you sure you have the correct molecules?\n" ) ; printf( "Continuing anyway\n" ) ; } /************/ /* Get angles */ Angles = generate_global_angles( angle_step ) ; printf( "Total number of rotations is %d\n" , Angles.n ) ; /************/ /* Assign charges */ if( electrostatics == 1 ) { printf( "Assigning charges\n" ) ; assign_charges( Static_Structure ) ; assign_charges( Mobile_Structure ) ; } /************/ /* Store new structures centered on Origin */ Origin_Static_Structure = translate_structure_onto_origin( Static_Structure ) ; Origin_Mobile_Structure = translate_structure_onto_origin( Mobile_Structure ) ; /* Free some memory */ for( i = 1 ; i <= Static_Structure.length ; i ++ ) { fftwf_free( Static_Structure.Residue[i].Atom ) ; } fftwf_free( Static_Structure.Residue ) ; for( i = 1 ; i <= Mobile_Structure.length ; i ++ ) { fftwf_free( Mobile_Structure.Residue[i].Atom ) ; } fftwf_free( Mobile_Structure.Residue ) ; /************/ /* Calculate Grid stuff */ grid_span = total_span_of_structures( Origin_Static_Structure , Origin_Mobile_Structure ) ; if( calculate == 1 ) { printf( "Using automatic calculation for grid size\n" ) ; global_grid_size = (int)( grid_span / reverse_calculated_one_span ) ; if( ( global_grid_size % 2 ) != 0 ) global_grid_size ++ ; } one_span = grid_span / (float)global_grid_size ; printf( "Span = %.3f angstroms\n" , grid_span ) ; printf( "Grid size = %d\n" , global_grid_size ) ; printf( "Each Grid cube = %.5f angstroms\n" , one_span ) ; /************/ /* Memory Allocation */ if( ( Scores = ( struct Score * ) fftwf_malloc ( ( keep_per_rotation + 2 ) * sizeof( struct Score ) ) ) == NULL ) { GENERAL_MEMORY_PROBLEM } if( ( ( static_grid = ( float * ) fftwf_malloc ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL ) || ( ( mobile_grid = ( float * ) fftwf_malloc ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL ) || ( ( convoluted_grid = ( float * ) fftwf_malloc ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL ) ) { printf( "Not enough memory for surface grids\nUse (sensible) smaller grid size\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } static_fsg = ( fftwf_complex * ) static_grid ; mobile_fsg = ( fftwf_complex * ) mobile_grid ; multiple_fsg = ( fftwf_complex * ) convoluted_grid ; if( electrostatics == 1 ) { if( ( ( static_elec_grid = ( float * ) fftwf_malloc ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL ) || ( ( mobile_elec_grid = ( float * ) fftwf_malloc ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL ) || ( ( convoluted_elec_grid = ( float * ) fftwf_malloc ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL ) ) { printf( "Not enough memory for electrostatic grids\nSwitch off electrostatics or use (sensible) smaller grid size\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } else { /* all ok */ printf( "Electrostatics are on\n" ) ; } static_elec_fsg = ( fftwf_complex * ) static_elec_grid ; mobile_elec_fsg = ( fftwf_complex * ) mobile_elec_grid ; multiple_elec_fsg = ( fftwf_complex * ) convoluted_elec_grid ; } /************/ /* Create FFTW plans */ printf( "Creating plans\n" ) ; plan_static_grid = fftwf_plan_dft_r2c_3d(global_grid_size, global_grid_size, global_grid_size, static_grid, static_grid, FFTW_MEASURE); plan_static_elec_grid = fftwf_plan_dft_r2c_3d(global_grid_size, global_grid_size, global_grid_size, static_elec_grid, static_elec_grid, FFTW_MEASURE); plan_mobile_grid = fftwf_plan_dft_r2c_3d(global_grid_size, global_grid_size, global_grid_size, mobile_grid, mobile_grid, FFTW_MEASURE); plan_mobile_elec_grid = fftwf_plan_dft_r2c_3d(global_grid_size, global_grid_size, global_grid_size, mobile_elec_grid, mobile_elec_grid, FFTW_MEASURE); plan_multiple_fsg = fftwf_plan_dft_c2r_3d(global_grid_size, global_grid_size, global_grid_size, multiple_fsg, multiple_fsg, FFTW_MEASURE); plan_multiple_elec_fsg = fftwf_plan_dft_c2r_3d(global_grid_size, global_grid_size, global_grid_size, multiple_elec_fsg, multiple_elec_fsg, FFTW_MEASURE); /************/ printf( "PCA TIMING SHOULD start here\n"); start_timing(); printf( "Setting up Static Structure\n" ) ; /* Discretise and surface the Static Structure (need do only once) */ discretise_structure( Origin_Static_Structure , grid_span , global_grid_size , static_grid ) ; printf( " surfacing grid\n" ) ; surface_grid( grid_span , global_grid_size , static_grid , surface , internal_value ) ; /* Calculate electic field at all grid nodes (need do only once) */ if( electrostatics == 1 ) { electric_field( Origin_Static_Structure , grid_span , global_grid_size , static_elec_grid ) ; electric_field_zero_core( global_grid_size , static_elec_grid , static_grid , internal_value ) ; } /* Fourier Transform the static grids (need do only once) */ printf( " one time forward FFT calculations\n" ) ; fftwf_execute(plan_static_grid); if( electrostatics == 1 ) { fftwf_execute(plan_static_elec_grid); } printf( " done\n" ) ; /************/ /* Store paramaters in case of rescue */ if( ( ftdock_file = fopen( "scratch_parameters.dat" , "w" ) ) == NULL ) { printf( "Could not open scratch_parameters.dat for writing.\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } fprintf( ftdock_file, "\nGlobal Scan\n" ) ; fprintf( ftdock_file, "\nCommand line controllable values\n" ) ; fprintf( ftdock_file, "Static molecule :: %s\n" , static_file_name ) ; fprintf( ftdock_file, "Mobile molecule :: %s\n" , mobile_file_name ) ; fprintf( ftdock_file, "Output file name :: %s\n" , output_file_name ) ; fprintf( ftdock_file, "\n" ) ; fprintf( ftdock_file, "Global grid size :: %6d %s\n" , global_grid_size , default_global_grid_size ) ; fprintf( ftdock_file, "Global search angle step :: %6d %s\n" , angle_step , default_angle_step ) ; fprintf( ftdock_file, "Global surface thickness :: %9.2f %s\n" , surface , default_surface ) ; fprintf( ftdock_file, "Global internal deterrent value :: %9.2f %s\n" , internal_value , default_internal_value ) ; if( electrostatics == 1 ) { fprintf( ftdock_file, "Electrostatics :: on %s\n" , default_electrostatics ) ; } else { fprintf( ftdock_file, "Electrostatics :: off %s\n" , default_electrostatics ) ; } fprintf( ftdock_file, "Global keep per rotation :: %6d %s\n" , keep_per_rotation , default_keep_per_rotation ) ; fprintf( ftdock_file, "\nCalculated values\n" ) ; fprintf( ftdock_file, "Global rotations :: %6d\n" , Angles.n ) ; fprintf( ftdock_file, "Global total span (angstroms) :: %10.3f\n" , grid_span ) ; fprintf( ftdock_file, "Global grid cell span (angstroms) :: %10.3f\n" , one_span ) ; fclose( ftdock_file ) ; /************/ /* Main program loop */ max_es_value = 0 ; printf( "Starting main loop through the rotations\n" ) ; /* PCA: start comment for( rotation = first_rotation ; rotation <= Angles.n ; rotation ++ ) { * PCA: end comment */ for( rotation = first_rotation ; rotation <= 10/*Angles.n*/ ; rotation ++ ) { printf( "." ) ; if( ( rotation % 50 ) == 0 ) printf( "\nRotation number %5d\n" , rotation ) ; /* Rotate Mobile Structure */ Rotated_at_Origin_Mobile_Structure = rotate_structure( Origin_Mobile_Structure , (int)Angles.z_twist[rotation] , (int)Angles.theta[rotation] , (int)Angles.phi[rotation] ) ; /* Discretise the rotated Mobile Structure */ discretise_structure( Rotated_at_Origin_Mobile_Structure , grid_span , global_grid_size , mobile_grid ) ; /* Electic point charge approximation onto grid calculations ( quicker than filed calculations by a long way! ) */ if( electrostatics == 1 ) { electric_point_charge( Rotated_at_Origin_Mobile_Structure , grid_span , global_grid_size , mobile_elec_grid ) ; } /* Forward Fourier Transforms */ fftwf_execute(plan_mobile_grid); if( electrostatics == 1 ) { fftwf_execute(plan_mobile_elec_grid); } /************/ /* Do convolution of the two sets of grids convolution is equivalent to multiplication of the complex conjugate of one fourier grid with other (raw) one hence the sign changes from a normal complex number multiplication */ for( fx = 0 ; fx < global_grid_size ; fx ++ ) { for( fy = 0 ; fy < global_grid_size ; fy ++ ) { for( fz = 0 ; fz < global_grid_size/2 + 1 ; fz ++ ) { fxyz = fz + ( global_grid_size/2 + 1 ) * ( fy + global_grid_size * fx ) ; multiple_fsg[fxyz][0] = static_fsg[fxyz][0] * mobile_fsg[fxyz][0] + static_fsg[fxyz][1] * mobile_fsg[fxyz][1] ; multiple_fsg[fxyz][1] = static_fsg[fxyz][1] * mobile_fsg[fxyz][0] - static_fsg[fxyz][0] * mobile_fsg[fxyz][1] ; if( electrostatics == 1 ) { multiple_elec_fsg[fxyz][0] = static_elec_fsg[fxyz][0] * mobile_elec_fsg[fxyz][0] + static_elec_fsg[fxyz][1] * mobile_elec_fsg[fxyz][1] ; multiple_elec_fsg[fxyz][1] = static_elec_fsg[fxyz][1] * mobile_elec_fsg[fxyz][0] - static_elec_fsg[fxyz][0] * mobile_elec_fsg[fxyz][1] ; } } } } /* Reverse Fourier Transform */ fftwf_execute(plan_multiple_fsg); if( electrostatics == 1 ) { fftwf_execute(plan_multiple_elec_fsg); } /************/ /* Get best scores */ for( i = 0 ; i < keep_per_rotation ; i ++ ) { Scores[i].score = 0 ; Scores[i].rpscore = 0.0 ; Scores[i].coord[1] = 0 ; Scores[i].coord[2] = 0 ; Scores[i].coord[3] = 0 ; } for( x = 0 ; x < global_grid_size ; x ++ ) { fx = x ; if( fx > ( global_grid_size / 2 ) ) fx -= global_grid_size ; for( y = 0 ; y < global_grid_size ; y ++ ) { fy = y ; if( fy > ( global_grid_size / 2 ) ) fy -= global_grid_size ; for( z = 0 ; z < global_grid_size ; z ++ ) { fz = z ; if( fz > ( global_grid_size / 2 ) ) fz -= global_grid_size ; xyz = z + ( 2 * ( global_grid_size / 2 + 1 ) ) * ( y + global_grid_size * x ) ; if( ( electrostatics == 0 ) || ( convoluted_elec_grid[xyz] < 0 ) ) { /* Scale factor from FFTs */ if( (int)convoluted_grid[xyz] != 0 ) { convoluted_grid[xyz] /= ( global_grid_size * global_grid_size * global_grid_size ) ; } if( (int)convoluted_grid[xyz] > Scores[keep_per_rotation-1].score ) { i = keep_per_rotation - 2 ; while( ( (int)convoluted_grid[xyz] > Scores[i].score ) && ( i >= 0 ) ) { Scores[i+1].score = Scores[i].score ; Scores[i+1].rpscore = Scores[i].rpscore ; Scores[i+1].coord[1] = Scores[i].coord[1] ; Scores[i+1].coord[2] = Scores[i].coord[2] ; Scores[i+1].coord[3] = Scores[i].coord[3] ; i -- ; } Scores[i+1].score = (int)convoluted_grid[xyz] ; if( ( electrostatics != 0 ) && ( convoluted_elec_grid[xyz] < 0.1 ) ) { Scores[i+1].rpscore = (float)convoluted_elec_grid[xyz] ; } else { Scores[i+1].rpscore = (float)0 ; } Scores[i+1].coord[1] = fx ; Scores[i+1].coord[2] = fy ; Scores[i+1].coord[3] = fz ; } } } } } if( rotation == 1 ) { if( ( ftdock_file = fopen( "scratch_scores.dat" , "w" ) ) == NULL ) { printf( "Could not open scratch_scores.dat for writing.\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } } else { if( ( ftdock_file = fopen( "scratch_scores.dat" , "a" ) ) == NULL ) { printf( "Could not open scratch_scores.dat for writing.\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } } for( i = 0 ; i < keep_per_rotation ; i ++ ) { max_es_value = min( max_es_value , Scores[i].rpscore ) ; /* PCA: start comment fprintf( ftdock_file, "G_DATA %6d %6d %7d %.0f %4d %4d %4d %4d%4d%4d\n" , rotation , 0 , Scores[i].score , (double)Scores[i].rpscore , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3 ] , Angles.z_twist[rotation] , Angles.theta[rotation] , Angles.phi[rotation] ) ; * PCA: Stop comment */ fprintf( stdout, "G_DATA %6d %6d %7d %4d %4d %4d %4d%4d%4d\n" , rotation , 0 , Scores[i].score , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3 ] , Angles.z_twist[rotation] , Angles.theta[rotation] , Angles.phi[rotation] ) ; } fclose( ftdock_file ) ; /* Free some memory */ for( i = 1 ; i <= Rotated_at_Origin_Mobile_Structure.length ; i ++ ) { fftwf_free( Rotated_at_Origin_Mobile_Structure.Residue[i].Atom ) ; } fftwf_free( Rotated_at_Origin_Mobile_Structure.Residue ) ; } /* Finished main loop */ /************/ /* Free the memory */ fftwf_destroy_plan(plan_static_grid); fftwf_destroy_plan(plan_static_elec_grid); fftwf_destroy_plan(plan_mobile_grid); fftwf_destroy_plan(plan_mobile_elec_grid); fftwf_destroy_plan(plan_multiple_fsg); fftwf_destroy_plan(plan_multiple_elec_fsg); fftwf_free( static_grid ) ; fftwf_free( mobile_grid ) ; fftwf_free( convoluted_grid ) ; if( electrostatics == 1 ) { fftwf_free( static_elec_grid ) ; fftwf_free( mobile_elec_grid ) ; fftwf_free( convoluted_elec_grid ) ; } for( i = 1 ; i <= Origin_Static_Structure.length ; i ++ ) { fftwf_free( Origin_Static_Structure.Residue[i].Atom ) ; } fftwf_free( Origin_Static_Structure.Residue ) ; for( i = 1 ; i <= Origin_Mobile_Structure.length ; i ++ ) { fftwf_free( Origin_Mobile_Structure.Residue[i].Atom ) ; } fftwf_free( Origin_Mobile_Structure.Residue ) ; /* PCA: Finishing programm here*/ printf("PCA TIMING SHOULD stop here\n"); end_timing(); printf("PCA STOPS HERE\n"); return 0; /* PCA: */ /************/ /* Read in all the scores */ printf( "\nReloading all the scores\n" ) ; if( ( ftdock_file = fopen( "scratch_scores.dat" , "r" ) ) == NULL ) { printf( "Could not open scratch_scores.dat for reading.\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } if( ( Scores = ( struct Score * ) realloc ( Scores , ( 1 + keep_per_rotation ) * Angles.n * sizeof( struct Score ) ) ) == NULL ) { printf( "Not enough memory left for storing scores\nProbably keeping too many per rotation\nDying\n\n" ) ; exit( EXIT_FAILURE ) ; } kept_scores = 0 ; while( fgets( line_buffer , 99 , ftdock_file ) ) { sscanf( line_buffer , "G_DATA %d %d %d %f %d %d %d %d %d %d" , &id , &id2 , &SCscore , &RPscore , &x , &y , &z , &z_twist , &theta , &phi ) ; Scores[kept_scores].score = SCscore ; Scores[kept_scores].rpscore = RPscore ; Scores[kept_scores].coord[1] = x ; Scores[kept_scores].coord[2] = y ; Scores[kept_scores].coord[3] = z ; Scores[kept_scores].angle[1] = z_twist ; Scores[kept_scores].angle[2] = theta ; Scores[kept_scores].angle[3] = phi ; kept_scores ++ ; } fclose( ftdock_file ) ; kept_scores -- ; qsort_scores( Scores , 0 , kept_scores ) ; /************/ /* Writing data file */ if( ( ftdock_file = fopen( output_file_name , "w" ) ) == NULL ) { printf( "Could not open %s for writing.\nDying\n\n" , output_file_name ) ; exit( EXIT_FAILURE ) ; } fprintf( ftdock_file, "FTDOCK data file\n" ) ; fprintf( ftdock_file, "\nGlobal Scan\n" ) ; fprintf( ftdock_file, "\nCommand line controllable values\n" ) ; fprintf( ftdock_file, "Static molecule :: %s\n" , static_file_name ) ; fprintf( ftdock_file, "Mobile molecule :: %s\n" , mobile_file_name ) ; fprintf( ftdock_file, "\n" ) ; fprintf( ftdock_file, "Global grid size :: %6d %s\n" , global_grid_size , default_global_grid_size ) ; fprintf( ftdock_file, "Global search angle step :: %6d %s\n" , angle_step , default_angle_step ) ; fprintf( ftdock_file, "Global surface thickness :: %9.2f %s\n" , surface , default_surface ) ; fprintf( ftdock_file, "Global internal deterrent value :: %9.2f %s\n" , internal_value , default_internal_value ) ; if( electrostatics == 1 ) { fprintf( ftdock_file, "Electrostatics :: on %s\n" , default_electrostatics ) ; } else { fprintf( ftdock_file, "Electrostatics :: off %s\n" , default_electrostatics ) ; } fprintf( ftdock_file, "Global keep per rotation :: %6d %s\n" , keep_per_rotation , default_keep_per_rotation ) ; fprintf( ftdock_file, "\nCalculated values\n" ) ; fprintf( ftdock_file, "Global rotations :: %6d\n" , Angles.n ) ; fprintf( ftdock_file, "Global total span (angstroms) :: %10.3f\n" , grid_span ) ; fprintf( ftdock_file, "Global grid cell span (angstroms) :: %10.3f\n" , one_span ) ; fprintf( ftdock_file, "\nData\n" ) ; fprintf( ftdock_file , "Type ID prvID SCscore ESratio Coordinates Angles\n\n" ) ; if( electrostatics == 1 ) { for( i = 0 ; i <= min( kept_scores , ( NUMBER_TO_KEEP - 1 ) ) ; i ++ ) { fprintf( ftdock_file, "G_DATA %6d %6d %7d %8.3f %4d %4d %4d %4d%4d%4d\n" , i + 1 , 0 , Scores[i].score , 100 * ( Scores[i].rpscore / max_es_value ) , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3] , Scores[i].angle[1] , Scores[i].angle[2] , Scores[i].angle[3] ) ; } } else { for( i = 0 ; i <= min( kept_scores , ( NUMBER_TO_KEEP - 1 ) ) ; i ++ ) { fprintf( ftdock_file, "G_DATA %6d %6d %7d %8.3f %4d %4d %4d %4d%4d%4d\n" , i + 1 , 0 , Scores[i].score , 0.0 , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3] , Scores[i].angle[1] , Scores[i].angle[2] , Scores[i].angle[3] ) ; } } fclose( ftdock_file ) ; /************/ printf( "\n\nFinished\n\n" ) ; return( 0 ) ; } /* end main */
void osd_work_queue_free(osd_work_queue *queue) { // if we have threads, clean them up if (queue->thread != NULL) { int threadnum; // stop the timer for "waittime" on the main thread if (queue->flags & WORK_QUEUE_FLAG_MULTI) { end_timing(queue->thread[queue->threads].waittime); } // signal all the threads to exit atomic_exchange32(&queue->exiting, TRUE); for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; if (thread->wakeevent != NULL) osd_event_set(thread->wakeevent); } // wait for all the threads to go away for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; // block on the thread going away, then close the handle if (thread->handle != NULL) { osd_thread_wait_free(thread->handle); } // clean up the wake event if (thread->wakeevent != NULL) osd_event_free(thread->wakeevent); } #if KEEP_STATISTICS int allocthreadnum; if (queue->flags & WORK_QUEUE_FLAG_MULTI) allocthreadnum = queue->threads + 1; else allocthreadnum = queue->threads; // output per-thread statistics for (threadnum = 0; threadnum < allocthreadnum; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime; printf("Thread %d: items=%9d run=%5.2f%% (%5.2f%%) spin=%5.2f%% wait/other=%5.2f%% total=%9d\n", threadnum, thread->itemsdone, (double)thread->runtime * 100.0 / (double)total, (double)thread->actruntime * 100.0 / (double)total, (double)thread->spintime * 100.0 / (double)total, (double)thread->waittime * 100.0 / (double)total, (UINT32) total); } #endif } // free the list if (queue->thread != NULL) osd_free(queue->thread); // free all the events if (queue->doneevent != NULL) osd_event_free(queue->doneevent); // free all items in the free list while (queue->free != NULL) { osd_work_item *item = (osd_work_item *)queue->free; queue->free = item->next; if (item->event != NULL) osd_event_free(item->event); osd_free(item); } // free all items in the active list while (queue->list != NULL) { osd_work_item *item = (osd_work_item *)queue->list; queue->list = item->next; if (item->event != NULL) osd_event_free(item->event); osd_free(item); } #if KEEP_STATISTICS printf("Items queued = %9d\n", queue->itemsqueued); printf("SetEvent calls = %9d\n", queue->setevents); printf("Extra items = %9d\n", queue->extraitems); printf("Spin loops = %9d\n", queue->spinloops); #endif osd_scalable_lock_free(queue->lock); // free the queue itself osd_free(queue); }
osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_callback callback, INT32 numitems, void *parambase, INT32 paramstep, UINT32 flags) { osd_work_item *itemlist = NULL, *lastitem = NULL; osd_work_item **item_tailptr = &itemlist; INT32 lockslot; int itemnum; // loop over items, building up a local list of work for (itemnum = 0; itemnum < numitems; itemnum++) { osd_work_item *item; // first allocate a new work item; try the free list first INT32 lockslot = osd_scalable_lock_acquire(queue->lock); do { item = (osd_work_item *)queue->free; } while (item != NULL && compare_exchange_ptr((PVOID volatile *)&queue->free, item, item->next) != item); osd_scalable_lock_release(queue->lock, lockslot); // if nothing, allocate something new if (item == NULL) { // allocate the item item = (osd_work_item *)osd_malloc(sizeof(*item)); if (item == NULL) return NULL; item->event = NULL; item->queue = queue; item->done = FALSE; } else { atomic_exchange32(&item->done, FALSE); // needs to be set this way to prevent data race/usage of uninitialized memory on Linux } // fill in the basics item->next = NULL; item->callback = callback; item->param = parambase; item->result = NULL; item->flags = flags; // advance to the next lastitem = item; *item_tailptr = item; item_tailptr = &item->next; parambase = (UINT8 *)parambase + paramstep; } // enqueue the whole thing within the critical section lockslot = osd_scalable_lock_acquire(queue->lock); *queue->tailptr = itemlist; queue->tailptr = item_tailptr; osd_scalable_lock_release(queue->lock, lockslot); // increment the number of items in the queue atomic_add32(&queue->items, numitems); add_to_stat(&queue->itemsqueued, numitems); // look for free threads to do the work if (queue->livethreads < queue->threads) { int threadnum; // iterate over all the threads for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; // if this thread is not active, wake him up if (!thread->active) { osd_event_set(thread->wakeevent); add_to_stat(&queue->setevents, 1); // for non-shared, the first one we find is good enough if (--numitems == 0) break; } } } // if no threads, run the queue now on this thread if (queue->threads == 0) { end_timing(queue->thread[0].waittime); worker_thread_process(queue, &queue->thread[0]); begin_timing(queue->thread[0].waittime); } // only return the item if it won't get released automatically return (flags & WORK_ITEM_FLAG_AUTO_RELEASE) ? NULL : lastitem; }
static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread) { int threadid = thread->id; begin_timing(thread->runtime); // loop until everything is processed while (true) { osd_work_item *item = nullptr; bool end_loop = false; // use a critical section to synchronize the removal of items { std::lock_guard<std::mutex> lock(queue->lock); if (queue->list.load() == nullptr) { end_loop = true; } else { // pull the item from the queue item = (osd_work_item *)queue->list; if (item != nullptr) { queue->list = item->next; if (queue->list.load() == nullptr) queue->tailptr = (osd_work_item **)&queue->list; } } } if (end_loop) break; // process non-NULL items if (item != nullptr) { // call the callback and stash the result begin_timing(thread->actruntime); item->result = (*item->callback)(item->param, threadid); end_timing(thread->actruntime); // decrement the item count after we are done --queue->items; item->done = TRUE; add_to_stat(thread->itemsdone, 1); // if it's an auto-release item, release it if (item->flags & WORK_ITEM_FLAG_AUTO_RELEASE) osd_work_item_release(item); // set the result and signal the event else { std::lock_guard<std::mutex> lock(queue->lock); if (item->event != nullptr) { item->event->set(); add_to_stat(item->queue.setevents, 1); } } // if we removed an item and there's still work to do, bump the stats if (queue_has_list_items(queue)) add_to_stat(queue->extraitems, 1); } } // we don't need to set the doneevent for multi queues because they spin if (queue->waiting) { queue->doneevent.set(); add_to_stat(queue->setevents, 1); } end_timing(thread->runtime); }
static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread) { int threadid = thread - queue->thread; begin_timing(thread->runtime); // loop until everything is processed while (true) { osd_work_item *item = NULL; bool end_loop = false; // use a critical section to synchronize the removal of items { INT32 lockslot = osd_scalable_lock_acquire(queue->lock); if (queue->list == NULL) { end_loop = true; } else { // pull the item from the queue item = (osd_work_item *)queue->list; if (item != NULL) { queue->list = item->next; if (queue->list == NULL) queue->tailptr = (osd_work_item **)&queue->list; } } osd_scalable_lock_release(queue->lock, lockslot); } if (end_loop) break; // process non-NULL items if (item != NULL) { // call the callback and stash the result begin_timing(thread->actruntime); item->result = (*item->callback)(item->param, threadid); end_timing(thread->actruntime); // decrement the item count after we are done atomic_decrement32(&queue->items); atomic_exchange32(&item->done, TRUE); add_to_stat(&thread->itemsdone, 1); // if it's an auto-release item, release it if (item->flags & WORK_ITEM_FLAG_AUTO_RELEASE) osd_work_item_release(item); // set the result and signal the event else { INT32 lockslot = osd_scalable_lock_acquire(item->queue->lock); if (item->event != NULL) { osd_event_set(item->event); add_to_stat(&item->queue->setevents, 1); } osd_scalable_lock_release(item->queue->lock, lockslot); } // if we removed an item and there's still work to do, bump the stats if (queue_has_list_items(queue)) add_to_stat(&queue->extraitems, 1); } } // we don't need to set the doneevent for multi queues because they spin if (queue->waiting) { osd_event_set(queue->doneevent); add_to_stat(&queue->setevents, 1); } end_timing(thread->runtime); }
int main() { int i; interface_init(); start_timing(); print_value("Timestamp bias", end_timing()); for (i = 0; i < TESTCASES1_COUNT; i++) { fix16_t input = testcases1[i].a; fix16_t result; fix16_t expected = testcases1[i].sqrt; MEASURE(sqrt_cycles, result = fix16_sqrt(input)); if (input > 0 && delta(result, expected) > max_delta) { print_value("Failed SQRT, i", i); print_value("Failed SQRT, input", input); print_value("Failed SQRT, output", result); print_value("Failed SQRT, expected", expected); } expected = testcases1[i].exp; MEASURE(exp_cycles, result = fix16_exp(input)); if (delta(result, expected) > 400) { print_value("Failed EXP, i", i); print_value("Failed EXP, input", input); print_value("Failed EXP, output", result); print_value("Failed EXP, expected", expected); } } PRINT(sqrt_cycles, "fix16_sqrt"); PRINT(exp_cycles, "fix16_exp"); for (i = 0; i < TESTCASES2_COUNT; i++) { fix16_t a = testcases2[i].a; fix16_t b = testcases2[i].b; volatile fix16_t result; fix16_t expected = testcases2[i].add; MEASURE(add_cycles, result = fix16_add(a, b)); if (delta(result, expected) > max_delta) { print_value("Failed ADD, i", i); print_value("Failed ADD, a", a); print_value("Failed ADD, b", b); print_value("Failed ADD, output", result); print_value("Failed ADD, expected", expected); } expected = testcases2[i].sub; MEASURE(sub_cycles, result = fix16_sub(a, b)); if (delta(result, expected) > max_delta) { print_value("Failed SUB, i", i); print_value("Failed SUB, a", a); print_value("Failed SUB, b", b); print_value("Failed SUB, output", result); print_value("Failed SUB, expected", expected); } expected = testcases2[i].mul; MEASURE(mul_cycles, result = fix16_mul(a, b)); if (delta(result, expected) > max_delta) { print_value("Failed MUL, i", i); print_value("Failed MUL, a", a); print_value("Failed MUL, b", b); print_value("Failed MUL, output", result); print_value("Failed MUL, expected", expected); } if (b != 0) { expected = testcases2[i].div; MEASURE(div_cycles, result = fix16_div(a, b)); if (delta(result, expected) > max_delta) { print_value("Failed DIV, i", i); print_value("Failed DIV, a", a); print_value("Failed DIV, b", b); print_value("Failed DIV, output", result); print_value("Failed DIV, expected", expected); } } } PRINT(add_cycles, "fix16_add"); PRINT(sub_cycles, "fix16_sub"); PRINT(mul_cycles, "fix16_mul"); PRINT(div_cycles, "fix16_div"); /* Compare with floating point performance */ #ifndef NO_FLOAT for (i = 0; i < TESTCASES1_COUNT; i++) { float input = fix16_to_float(testcases1[i].a); volatile float result; MEASURE(float_sqrtf_cycles, result = sqrtf(input)); } PRINT(float_sqrtf_cycles, "float sqrtf"); for (i = 0; i < TESTCASES2_COUNT; i++) { float a = fix16_to_float(testcases2[i].a); float b = fix16_to_float(testcases2[i].b); volatile float result; MEASURE(float_add_cycles, result = a + b); MEASURE(float_sub_cycles, result = a - b); MEASURE(float_mul_cycles, result = a * b); if (b != 0) { MEASURE(float_div_cycles, result = a / b); } } PRINT(float_add_cycles, "float add"); PRINT(float_sub_cycles, "float sub"); PRINT(float_mul_cycles, "float mul"); PRINT(float_div_cycles, "float div"); #endif return 0; }