void create_ff_refine_task(Element *e1, Element *e2, long level, long process_id) { Task *t ; /* Check existing parallelism */ if( taskq_too_long(&global->task_queue[ taskqueue_id[process_id] ], n_tasks_per_queue) ) { /* Task queue is too long. Solve it immediately */ ff_refine_elements( e1, e2, level, process_id ) ; return ; } /* Create a task */ t = get_task(process_id) ; t->task_type = TASK_FF_REFINEMENT ; t->task.ref.e1 = e1 ; t->task.ref.e2 = e2 ; t->task.ref.level = level ; /* Put in the queue */ enqueue_task( taskqueue_id[process_id], t, TASK_INSERT ) ; }
void process_tasks(long process_id) { Task *t ; retry_entry: t = DEQUEUE_TASK( taskqueue_id[process_id], QUEUES_VISITED, process_id ) ; while( t ) { switch( t->task_type ) { case TASK_MODELING: process_model( t->task.model.model, t->task.model.type, process_id ) ; break ; case TASK_BSP: define_patch( t->task.bsp.patch, t->task.bsp.parent, process_id ) ; break ; case TASK_FF_REFINEMENT: ff_refine_elements( t->task.ref.e1, t->task.ref.e2, 0, process_id ) ; break ; case TASK_RAY: process_rays( t->task.ray.e, process_id ) ; break ; case TASK_VISIBILITY: visibility_task( t->task.vis.e, t->task.vis.inter, t->task.vis.n_inter, t->task.vis.k, process_id ) ; break ; case TASK_RAD_AVERAGE: radiosity_averaging( t->task.rad.e, t->task.rad.mode, process_id ) ; break ; default: fprintf( stderr, "Panic:process_tasks:Illegal task type\n" ); } /* Free the task */ free_task( t, process_id ) ; /* Get next task */ t = DEQUEUE_TASK( taskqueue_id[process_id], QUEUES_VISITED, process_id ) ; } /* Barrier. While waiting for other processors to finish, poll the task queues and resume processing if there is any task */ LOCK(global->pbar_lock); /* Reset the barrier counter if not initialized */ if( global->pbar_count >= n_processors ) global->pbar_count = 0 ; /* Increment the counter */ global->pbar_count++ ; /* barrier spin-wait loop */ long bar_done = !(global->pbar_count < n_processors); UNLOCK(global->pbar_lock); while(!bar_done) { /* Wait for a while and then retry dequeue */ if( _process_task_wait_loop() ) break ; /* Waited for a while but other processors are still running. Poll the task queue again If polling succeeds (without actually getting a task) then we exit the barrier and try to get a task. This fixes the bug where all the threads might finish the barrier but in the meantime one reenters it to process some tasks. */ int has_task = peek_dequeue( taskqueue_id[process_id], QUEUES_VISITED, process_id ); if (has_task) { LOCK(global->pbar_lock); global->pbar_count-- ; UNLOCK(global->pbar_lock); goto retry_entry ; } LOCK(global->pbar_lock); bar_done = !(global->pbar_count < n_processors); UNLOCK(global->pbar_lock); } BARRIER(global->barrier, n_processors); }
void process_tasks(long process_id) { Task *t ; t = DEQUEUE_TASK( taskqueue_id[process_id], QUEUES_VISITED, process_id ) ; retry_entry: while( t ) { switch( t->task_type ) { case TASK_MODELING: process_model( t->task.model.model, t->task.model.type, process_id ) ; break ; case TASK_BSP: define_patch( t->task.bsp.patch, t->task.bsp.parent, process_id ) ; break ; case TASK_FF_REFINEMENT: ff_refine_elements( t->task.ref.e1, t->task.ref.e2, 0, process_id ) ; break ; case TASK_RAY: process_rays( t->task.ray.e, process_id ) ; break ; case TASK_VISIBILITY: visibility_task( t->task.vis.e, t->task.vis.inter, t->task.vis.n_inter, t->task.vis.k, process_id ) ; break ; case TASK_RAD_AVERAGE: radiosity_averaging( t->task.rad.e, t->task.rad.mode, process_id ) ; break ; default: fprintf( stderr, "Panic:process_tasks:Illegal task type\n" ); } /* Free the task */ free_task( t, process_id ) ; /* Get next task */ t = DEQUEUE_TASK( taskqueue_id[process_id], QUEUES_VISITED, process_id ) ; } /* Barrier. While waiting for other processors to finish, poll the task queues and resume processing if there is any task */ LOCK(global->pbar_lock); /* Reset the barrier counter if not initialized */ if( global->pbar_count >= n_processors ) global->pbar_count = 0 ; /* Increment the counter */ global->pbar_count++ ; UNLOCK(global->pbar_lock); /* barrier spin-wait loop */ while( global->pbar_count < n_processors ) { /* Wait for a while and then retry dequeue */ if( _process_task_wait_loop() ) break ; /* Waited for a while but other processors are still running. Poll the task queue again */ t = DEQUEUE_TASK( taskqueue_id[process_id], QUEUES_VISITED, process_id ) ; if( t ) { /* Task found. Exit the barrier and work on it */ LOCK(global->pbar_lock); global->pbar_count-- ; UNLOCK(global->pbar_lock); goto retry_entry ; } } BARRIER(global->barrier, n_processors); }
void ff_refine_elements(Element *e1, Element *e2, long level, long process_id) { long subdiv_advice ; Interaction i12, i21 ; Interaction *inter ; #if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_COSTBASED Patch_Cost *pc1, *pc2 ; long cost1, cost2 ; #endif /* Now compute formfactor. As the BSP tree is being modified at this moment, don't test visibility. */ compute_formfactor( e1, e2, &i12, process_id ) ; compute_formfactor( e2, e1, &i21, process_id ) ; /* Analyze the error of FF */ subdiv_advice = error_analysis( e1, e2, &i12, &i21, process_id ) ; /* Execute subdivision procedure */ if( NO_INTERACTION(subdiv_advice) ) /* Two elements are mutually invisible. Do nothing */ return ; else if( NO_REFINEMENT_NECESSARY(subdiv_advice) ) { /* Create links and finish the job */ inter = get_interaction(process_id) ; *inter = i12 ; inter->visibility = VISIBILITY_UNDEF ; insert_vis_undef_interaction( e1, inter, process_id ) ; inter = get_interaction(process_id) ; *inter = i21 ; inter->visibility = VISIBILITY_UNDEF ; insert_vis_undef_interaction( e2, inter, process_id ) ; #if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_COSTBASED /* Update cost variable */ pc1 = &global->patch_cost[ e1->patch->seq_no ] ; pc2 = &global->patch_cost[ e2->patch->seq_no ] ; if( pc1->n_total_inter <= 13 ) cost1 = (long)ceil(e1->area / Area_epsilon) ; else cost1 = 1 ; if( pc2->n_total_inter <= 13 ) cost2 = (long)ceil(e2->area / Area_epsilon) ; else cost2 = 1 ; LOCK(global->cost_sum_lock); pc1->cost_estimate += cost1 ; pc1->n_total_inter++ ; pc2->cost_estimate += cost2 ; pc2->n_total_inter++ ; global->cost_estimate_sum += (cost1 + cost2) ; global->cost_sum += (cost1 + cost2) ; UNLOCK(global->cost_sum_lock); #endif } else if( REFINE_PATCH_1(subdiv_advice) ) { /* Refine patch 1 */ subdivide_element( e1, process_id ) ; /* Locally solve it */ ff_refine_elements( e1->top, e2, level+1, process_id ) ; ff_refine_elements( e1->center, e2, level+1, process_id ) ; ff_refine_elements( e1->left, e2, level+1, process_id ) ; ff_refine_elements( e1->right, e2, level+1, process_id ) ; } else { /* Refine patch 2 */ subdivide_element( e2, process_id ) ; /* Locally solve it */ ff_refine_elements( e1, e2->top, level+1, process_id ) ; ff_refine_elements( e1, e2->center, level+1, process_id ) ; ff_refine_elements( e1, e2->left, level+1, process_id ) ; ff_refine_elements( e1, e2->right, level+1, process_id ) ; } }