void pb_SwitchToTimer(struct pb_TimerSet *timers, enum pb_TimerID timer) { /* Stop the currently running timer */ if (timers->current != pb_TimerID_NONE) { struct pb_SubTimer *currSubTimer = NULL; struct pb_SubTimerList *subtimerlist = timers->sub_timer_list[timers->current]; if ( subtimerlist != NULL) { currSubTimer = timers->sub_timer_list[timers->current]->current; } if ( currSubTimer!= NULL) { pb_StopTimerAndSubTimer(&timers->timers[timers->current], &currSubTimer->timer); } else { pb_StopTimer(&timers->timers[timers->current]); } } timers->current = timer; if (timer != pb_TimerID_NONE) { pb_StartTimer(&timers->timers[timer]); } }
void pb_SwitchToTimer(struct pb_TimerSet *timers, enum pb_TimerID timer) { /* Stop the currently running timer */ if (timers->current != pb_TimerID_NONE) pb_StopTimer(&timers->timers[timers->current]); timers->current = timer; /* Start the new timer */ if (timer != pb_TimerID_NONE) pb_StartTimer(&timers->timers[timer]); }
void pb_SwitchToSubTimer(struct pb_TimerSet *timers, char *label, enum pb_TimerID category) { struct pb_SubTimerList *subtimerlist = timers->sub_timer_list[timers->current]; struct pb_SubTimer *curr = (subtimerlist != NULL) ? subtimerlist->current : NULL; if (timers->current != pb_TimerID_NONE) { if (!is_async(timers->current) ) { if (timers->current != category) { if (curr != NULL) { pb_StopTimerAndSubTimer(&timers->timers[timers->current], &curr->timer); } else { pb_StopTimer(&timers->timers[timers->current]); } } else { if (curr != NULL) { pb_StopTimer(&curr->timer); } } } else { insert_submarker(timers, label, category); if (!is_async(category)) { // if switching to async too, keep driver going pb_StopTimer(&timers->timers[pb_TimerID_DRIVER]); } } } pb_Timestamp currentTime = get_time(); /* The only cases we check for asynchronous task completion is * when an overlapping CPU operation completes, or the next * segment blocks on completion of previous async operations */ if( asyncs_outstanding(timers) && (!is_async(timers->current) || is_blocking(category) ) ) { struct pb_async_time_marker_list * last_event = get_last_async(timers); /* cudaSuccess if completed */ cudaError_t async_done = cudaEventQuery(*((cudaEvent_t *)last_event->marker)); if(is_blocking(category)) { /* Async operations completed after previous CPU operations: * overlapped time is the total CPU time since this set of async * operations were first issued */ // timer to switch to is COPY or NONE // if it hasn't already finished, then just take now and use that as the elapsed time in OVERLAP // anything happening after now isn't OVERLAP because everything is being stopped to wait for synchronization // it seems that the extra sync wall time isn't being recorded anywhere if(async_done != cudaSuccess) accumulate_time(&(timers->timers[pb_TimerID_OVERLAP].elapsed), timers->async_begin,currentTime); /* Wait on async operation completion */ cudaEventSynchronize(*((cudaEvent_t *)last_event->marker)); pb_Timestamp total_async_time = record_async_times(timers); /* Async operations completed before previous CPU operations: * overlapped time is the total async time */ // If it did finish, then accumulate all the async time that did happen into OVERLAP // the immediately preceding EventSynchronize theoretically didn't have any effect since it was already completed. if(async_done == cudaSuccess) timers->timers[pb_TimerID_OVERLAP].elapsed += total_async_time; } else /* implies (!is_async(timers->current) && asyncs_outstanding(timers)) */ // i.e. Current Not Async (not KERNEL/COPY_ASYNC) but there are outstanding // so something is deeper in stack if(async_done == cudaSuccess) { /* Async operations completed before previous CPU operations: * overlapped time is the total async time */ timers->timers[pb_TimerID_OVERLAP].elapsed += record_async_times(timers); } // else, this isn't blocking, so just check the next time around } subtimerlist = timers->sub_timer_list[category]; struct pb_SubTimer *subtimer = NULL; if (label != NULL) { subtimer = subtimerlist->subtimer_list; while (subtimer != NULL) { if (strcmp(subtimer->label, label) == 0) { break; } else { subtimer = subtimer->next; } } } /* Start the new timer */ if (category != pb_TimerID_NONE) { if(!is_async(category)) { if (subtimerlist != NULL) { subtimerlist->current = subtimer; } if (category != timers->current && subtimer != NULL) { pb_StartTimerAndSubTimer(&timers->timers[category], &subtimer->timer); } else if (subtimer != NULL) { pb_StartTimer(&subtimer->timer); } else { pb_StartTimer(&timers->timers[category]); } } else { if (subtimerlist != NULL) { subtimerlist->current = subtimer; } // toSwitchTo Is Async (KERNEL/COPY_ASYNC) if (!asyncs_outstanding(timers)) { /* No asyncs outstanding, insert a fresh async marker */ insert_submarker(timers, label, category); timers->async_begin = currentTime; } else if(!is_async(timers->current)) { /* Previous asyncs still in flight, but a previous SwitchTo * already marked the end of the most recent async operation, * so we can rename that marker as the beginning of this async * operation */ struct pb_async_time_marker_list * last_event = get_last_async(timers); last_event->timerID = category; last_event->label = label; } // else, marker for switchToThis was already inserted //toSwitchto is already asynchronous, but if current/prev state is async too, then DRIVER is already running if (!is_async(timers->current)) { pb_StartTimer(&timers->timers[pb_TimerID_DRIVER]); } } } timers->current = category; }
void pb_SwitchToTimer(struct pb_TimerSet *timers, enum pb_TimerID timer) { /* Stop the currently running timer */ if (timers->current != pb_TimerID_NONE) { struct pb_SubTimerList *subtimerlist = timers->sub_timer_list[timers->current]; struct pb_SubTimer *currSubTimer = (subtimerlist != NULL) ? subtimerlist->current : NULL; if (!is_async(timers->current) ) { if (timers->current != timer) { if (currSubTimer != NULL) { pb_StopTimerAndSubTimer(&timers->timers[timers->current], &currSubTimer->timer); } else { pb_StopTimer(&timers->timers[timers->current]); } } else { if (currSubTimer != NULL) { pb_StopTimer(&currSubTimer->timer); } } } else { insert_marker(timers, timer); if (!is_async(timer)) { // if switching to async too, keep driver going pb_StopTimer(&timers->timers[pb_TimerID_DRIVER]); } } } pb_Timestamp currentTime = get_time(); /* The only cases we check for asynchronous task completion is * when an overlapping CPU operation completes, or the next * segment blocks on completion of previous async operations */ if( asyncs_outstanding(timers) && (!is_async(timers->current) || is_blocking(timer) ) ) { struct pb_async_time_marker_list * last_event = get_last_async(timers); /* cudaSuccess if completed */ cudaError_t async_done = cudaEventQuery(*((cudaEvent_t *)last_event->marker)); if(is_blocking(timer)) { /* Async operations completed after previous CPU operations: * overlapped time is the total CPU time since this set of async * operations were first issued */ // timer to switch to is COPY or NONE if(async_done != cudaSuccess) accumulate_time(&(timers->timers[pb_TimerID_OVERLAP].elapsed), timers->async_begin,currentTime); /* Wait on async operation completion */ cudaEventSynchronize(*((cudaEvent_t *)last_event->marker)); pb_Timestamp total_async_time = record_async_times(timers); /* Async operations completed before previous CPU operations: * overlapped time is the total async time */ if(async_done == cudaSuccess) timers->timers[pb_TimerID_OVERLAP].elapsed += total_async_time; } else /* implies (!is_async(timers->current) && asyncs_outstanding(timers)) */ // i.e. Current Not Async (not KERNEL/COPY_ASYNC) but there are outstanding // so something is deeper in stack if(async_done == cudaSuccess) { /* Async operations completed before previous CPU operations: * overlapped time is the total async time */ timers->timers[pb_TimerID_OVERLAP].elapsed += record_async_times(timers); } } /* Start the new timer */ if (timer != pb_TimerID_NONE) { if(!is_async(timer)) { pb_StartTimer(&timers->timers[timer]); } else { // toSwitchTo Is Async (KERNEL/COPY_ASYNC) if (!asyncs_outstanding(timers)) { /* No asyncs outstanding, insert a fresh async marker */ insert_marker(timers, timer); timers->async_begin = currentTime; } else if(!is_async(timers->current)) { /* Previous asyncs still in flight, but a previous SwitchTo * already marked the end of the most recent async operation, * so we can rename that marker as the beginning of this async * operation */ struct pb_async_time_marker_list * last_event = get_last_async(timers); last_event->label = NULL; last_event->timerID = timer; } if (!is_async(timers->current)) { pb_StartTimer(&timers->timers[pb_TimerID_DRIVER]); } } } timers->current = timer; }
void pb_SwitchToSubTimer(struct pb_TimerSet *timers, char *label, enum pb_TimerID category) { // switchToSub( NULL, NONE // switchToSub( NULL, some // switchToSub( some, some // switchToSub( some, NONE -- tries to find "some" in NONE's sublist, which won't be printed struct pb_Timer *topLevelToStop = NULL; if (timers->current != category && timers->current != pb_TimerID_NONE) { // Switching to subtimer in a different category needs to stop the top-level current, different categoried timer. // NONE shouldn't have a timer associated with it, so exclude from branch topLevelToStop = &timers->timers[timers->current]; } struct pb_SubTimerList *subtimerlist = timers->sub_timer_list[timers->current]; struct pb_SubTimer *curr = (subtimerlist == NULL) ? NULL : subtimerlist->current; if (timers->current != pb_TimerID_NONE) { if (curr != NULL && topLevelToStop != NULL) { pb_StopTimerAndSubTimer(topLevelToStop, &curr->timer); } else if (curr != NULL) { pb_StopTimer(&curr->timer); } else { pb_StopTimer(topLevelToStop); } } subtimerlist = timers->sub_timer_list[category]; struct pb_SubTimer *subtimer = NULL; if (label != NULL) { subtimer = subtimerlist->subtimer_list; while (subtimer != NULL) { if (strcmp(subtimer->label, label) == 0) { break; } else { subtimer = subtimer->next; } } } if (category != pb_TimerID_NONE) { if (subtimerlist != NULL) { subtimerlist->current = subtimer; } if (category != timers->current && subtimer != NULL) { pb_StartTimerAndSubTimer(&timers->timers[category], &subtimer->timer); } else if (subtimer != NULL) { // Same category, different non-NULL subtimer pb_StartTimer(&subtimer->timer); } else{ // Different category, but no subtimer (not found or specified as NULL) -- unprefered way of setting topLevel timer pb_StartTimer(&timers->timers[category]); } } timers->current = category; }