537 lines
18 KiB
C
537 lines
18 KiB
C
/*************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 1994 Stanford University */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Permission is given to use, copy, and modify this software for any */
|
|
/* non-commercial purpose as long as this copyright notice is not */
|
|
/* removed. All other uses, including redistribution in whole or in */
|
|
/* part, are forbidden without prior written permission. */
|
|
/* */
|
|
/* This software is provided with absolutely no warranty and no */
|
|
/* support. */
|
|
/* */
|
|
/*************************************************************************/
|
|
|
|
/**************************************************************
|
|
*
|
|
* Utility package
|
|
*
|
|
***************************************************************/
|
|
|
|
#include <stdio.h>
|
|
|
|
EXTERN_ENV;
|
|
|
|
include(radiosity.h)
|
|
|
|
static void clear_element_radiosity(Element *elem, long dummy, long process_id);
|
|
|
|
/***************************************
|
|
*
|
|
* Global variables
|
|
*
|
|
****************************************/
|
|
|
|
#define MAX_INTERACTION_PER_ELEMENT (100)
|
|
|
|
long total_patches ;
|
|
long total_elements ;
|
|
long total_equiv_elements ;
|
|
long total_interactions ;
|
|
long total_comp_visible_interactions ;
|
|
long total_invisible_interactions ;
|
|
long total_match3, total_match2, total_match1, total_match0 ;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
long count ;
|
|
float area ;
|
|
} Elem_Interaction ;
|
|
|
|
Elem_Interaction elem_interaction[MAX_INTERACTION_PER_ELEMENT+1] ;
|
|
Elem_Interaction many_interaction ;
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* Prinit statistics
|
|
*
|
|
****************************************/
|
|
|
|
void print_statistics(FILE *fd, long process_id)
|
|
{
|
|
long i ;
|
|
|
|
/* Initialize information */
|
|
total_patches = 0 ;
|
|
total_elements = 0 ;
|
|
total_equiv_elements = 0 ;
|
|
total_interactions = 0 ;
|
|
total_comp_visible_interactions = 0 ;
|
|
total_invisible_interactions = 0 ;
|
|
total_match3 = 0 ;
|
|
total_match2 = 0 ;
|
|
total_match1 = 0 ;
|
|
total_match0 = 0 ;
|
|
|
|
for( i = 0 ; i < MAX_INTERACTION_PER_ELEMENT ; i++ )
|
|
{
|
|
elem_interaction[i].count = 0 ;
|
|
elem_interaction[i].area = 0 ;
|
|
}
|
|
many_interaction.count = 0 ;
|
|
many_interaction.area = 0 ;
|
|
|
|
foreach_patch_in_bsp( get_patch_stat, 0, 0 ) ;
|
|
|
|
fprintf( fd, "Rasiosity Statistics\n\n" ) ;
|
|
|
|
fprintf( fd, " Histogram of interactions/elem\n" ) ;
|
|
fprintf( fd, "\t Interactions Occurrence\n" ) ;
|
|
fprintf( fd, "\t -------------------------------\n" ) ;
|
|
if( many_interaction.count > 0 )
|
|
{
|
|
fprintf( fd, "\t (Over %d) %ld (%f)\n",
|
|
MAX_INTERACTION_PER_ELEMENT,
|
|
many_interaction.count,
|
|
many_interaction.area / many_interaction.count ) ;
|
|
}
|
|
for( i = MAX_INTERACTION_PER_ELEMENT ;
|
|
elem_interaction[i].count == 0 ; i-- ) ;
|
|
for( ; i >= 0 ; i-- )
|
|
{
|
|
if( elem_interaction[i].count == 0 )
|
|
continue ;
|
|
|
|
if( elem_interaction[i].count == 0 )
|
|
fprintf( fd, "\t %ld %ld (---)\n",
|
|
i, elem_interaction[i].count ) ;
|
|
|
|
else
|
|
fprintf( fd, "\t %ld %ld (%f)\n",
|
|
i, elem_interaction[i].count,
|
|
elem_interaction[i].area / elem_interaction[i].count);
|
|
}
|
|
|
|
fprintf( fd, " Configurations\n" ) ;
|
|
#if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_COSTBASED
|
|
fprintf( fd, "\tPatch assignment: Costbased\n" ) ;
|
|
fprintf( fd, "\tUsing non-greedy cost-based algorithm\n") ;
|
|
#endif
|
|
#if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_STATIC
|
|
fprintf( fd, "\tPatch assignment: Static equal number\n" ) ;
|
|
#endif
|
|
|
|
fprintf( fd, "\tAlways inserting at top of list for visibility testing (not sorted)\n" ) ;
|
|
fprintf( fd, "\tRecursive pruning enabled for BSP tree traversal\n" ) ;
|
|
fprintf( fd, "\tPatch cache: Enabled\n" ) ;
|
|
fprintf( fd, "\tAlways check all other queues when task stealing (not neighbor scheme)\n" ) ;
|
|
|
|
|
|
fprintf( fd, " Parameters\n" ) ;
|
|
fprintf( fd, "\tNumber of processors: %ld\n", n_processors ) ;
|
|
fprintf( fd, "\tNumber of task queues: %ld\n", n_taskqueues ) ;
|
|
fprintf( fd, "\tNumber of tasks / queue: %ld\n", n_tasks_per_queue ) ;
|
|
fprintf( fd, "\tArea epsilon: %f\n", Area_epsilon ) ;
|
|
fprintf( fd, "\t#inter parallel refine: %ld\n",
|
|
N_inter_parallel_bf_refine);
|
|
fprintf( fd, "\t#visibility comp / task: %ld\n", N_visibility_per_task ) ;
|
|
fprintf( fd, "\tBF epsilon: %f\n", BFepsilon ) ;
|
|
fprintf( fd, "\tEnergy convergence: %f\n", Energy_epsilon ) ;
|
|
|
|
fprintf( fd, " Iterations to converge: %ld times\n",
|
|
global->iteration_count ) ;
|
|
|
|
fprintf( fd, " Resource Usage\n" ) ;
|
|
fprintf( fd, "\tNumber of patches: %ld\n", total_patches ) ;
|
|
fprintf( fd, "\tTotal number of elements: %ld\n", total_elements ) ;
|
|
fprintf( fd, "\tTotal number of interactions: %ld\n", total_interactions);
|
|
fprintf( fd, "\t completely visible: %ld\n",
|
|
total_comp_visible_interactions ) ;
|
|
fprintf( fd, "\t completely invisible: %ld\n",
|
|
total_invisible_interactions ) ;
|
|
fprintf( fd, "\t partially visible: %ld\n",
|
|
total_interactions - total_comp_visible_interactions
|
|
- total_invisible_interactions ) ;
|
|
fprintf( fd, "\tInteraction coherence (root interaction not counted)\n");
|
|
fprintf( fd, "\t Common for 4 siblings: %ld\n", total_match3 ) ;
|
|
fprintf( fd, "\t Common for 3 siblings: %ld\n", total_match2 ) ;
|
|
fprintf( fd, "\t Common for 2 siblings: %ld\n", total_match1 ) ;
|
|
fprintf( fd, "\t Common for no sibling: %ld\n", total_match0 ) ;
|
|
fprintf( fd, "\tAvg. elements per patch: %.1f\n",
|
|
(float)total_elements / (float)total_patches ) ;
|
|
fprintf( fd, "\tAvg. interactions per patch: %.1f\n",
|
|
(float)total_interactions / (float)total_patches ) ;
|
|
fprintf( fd, "\tAvg. interactions per element:%.1f\n",
|
|
(float)total_interactions / (float)total_elements ) ;
|
|
fprintf( fd, "\tNumber of elements in equivalent uniform mesh: %ld\n",
|
|
total_equiv_elements ) ;
|
|
fprintf( fd, "\tElem(hierarchical)/Elem(uniform): %.2f%%\n",
|
|
(float)total_elements / (float)total_equiv_elements * 100.0 ) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
*
|
|
* print_per_process_info()
|
|
*
|
|
***********************************************************/
|
|
|
|
void print_per_process_info(FILE *fd, long process)
|
|
{
|
|
long cache_line ;
|
|
long iteration ;
|
|
StatisticalInfo *ps ;
|
|
Element *e ;
|
|
|
|
ps = &global->stat_info[process] ;
|
|
|
|
fprintf( fd, "\t\tModeling tasks: %ld\n",
|
|
ps->total_modeling_tasks ) ;
|
|
fprintf( fd, "\t\tDefine patch tasks: %ld\n",
|
|
ps->total_def_patch_tasks ) ;
|
|
fprintf( fd, "\t\tFF refinement tasks: %ld\n",
|
|
ps->total_ff_ref_tasks ) ;
|
|
fprintf( fd, "\t\tRay processing tasks: %ld\n",
|
|
ps->total_ray_tasks ) ;
|
|
fprintf( fd, "\t\tRadiosity Avg/Norm tasks: %ld\n",
|
|
ps->total_radavg_tasks ) ;
|
|
fprintf( fd, "\t\tInteraction computations: %ld\n",
|
|
ps->total_interaction_comp ) ;
|
|
fprintf( fd, "\t\tVisibility computations: %ld\n",
|
|
ps->total_visibility_comp ) ;
|
|
fprintf( fd, "\t\t (%ld of %ld were partially visible)\n",
|
|
ps->partially_visible,
|
|
ps->total_visibility_comp ) ;
|
|
fprintf( fd, "\t\tRay intersection tests: %ld\n",
|
|
ps->total_ray_intersect_test ) ;
|
|
fprintf( fd, "\t\tPatch cache hit ratio: %.2f%%\n",
|
|
ps->total_patch_cache_hit * 100 /
|
|
(ps->total_patch_cache_check + 0.01) ) ;
|
|
for( cache_line = 0 ; cache_line < PATCH_CACHE_SIZE ; cache_line++ )
|
|
fprintf( fd, "\t\t (level %ld): %.2f%%\n",
|
|
cache_line,
|
|
ps->patch_cache_hit[cache_line] * 100 /
|
|
(ps->total_patch_cache_check + 0.01));
|
|
|
|
/* Per iteration info */
|
|
fprintf( fd, "\t\tPer iteration info.\n" ) ;
|
|
for( iteration = 0 ; iteration < global->iteration_count ; iteration++ )
|
|
{
|
|
fprintf( fd, "\t\t [%ld] Interaction comp: %ld\n",
|
|
iteration, ps->per_iteration[iteration].visibility_comp ) ;
|
|
fprintf( fd, "\t\t Ray Intersection: %ld\n",
|
|
ps->per_iteration[iteration].ray_intersect_test ) ;
|
|
fprintf( fd, "\t\t Tasks from my Q: %ld\n",
|
|
ps->per_iteration[iteration].tasks_from_myq ) ;
|
|
fprintf( fd, "\t\t Tasks from other Q: %ld\n",
|
|
ps->per_iteration[iteration].tasks_from_otherq ) ;
|
|
fprintf( fd, "\t\t Process_task wait count: %ld\n",
|
|
ps->per_iteration[iteration].process_tasks_wait ) ;
|
|
e = ps->per_iteration[iteration].last_pr_task ;
|
|
if( e == 0 )
|
|
continue ;
|
|
if( e->parent == 0 )
|
|
{
|
|
fprintf( fd, "\t\t Last task: Patch level\n" ) ;
|
|
fprintf( fd, "\t\t (%ld root inter)\n",
|
|
e->n_interactions ) ;
|
|
}
|
|
else
|
|
{
|
|
fprintf( fd, "\t\t Last task: Elem level\n" ) ;
|
|
fprintf( fd, "\t\t (%ld inter, %.3f Elem/Patch)\n",
|
|
e->n_interactions, e->area / e->patch->area ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************
|
|
*
|
|
* get_patch_stat()
|
|
*
|
|
***********************************************************/
|
|
|
|
long n_elements_in_patch ;
|
|
long n_equiv_elem_in_patch ;
|
|
float min_elem_area ;
|
|
long n_interactions_in_patch ;
|
|
long n_comp_visible_interactions ;
|
|
long n_invisible_interactions ;
|
|
|
|
|
|
void get_patch_stat(Patch *patch, long dummy, long process_id)
|
|
{
|
|
/* Initialize stat info for element */
|
|
n_elements_in_patch = 0 ;
|
|
n_equiv_elem_in_patch = 1 ;
|
|
min_elem_area = patch->area ;
|
|
n_interactions_in_patch = 0 ;
|
|
n_comp_visible_interactions = 0 ;
|
|
n_invisible_interactions = 0 ;
|
|
|
|
/* Traverse the quad tree */
|
|
foreach_element_in_patch( patch, get_elem_stat, 0, process_id ) ;
|
|
|
|
/* Update global stat variables */
|
|
total_patches++ ;
|
|
total_elements += n_elements_in_patch ;
|
|
total_equiv_elements += n_equiv_elem_in_patch ;
|
|
total_interactions += n_interactions_in_patch ;
|
|
total_comp_visible_interactions += n_comp_visible_interactions ;
|
|
total_invisible_interactions += n_invisible_interactions ;
|
|
|
|
#if PATCH_ASSIGNMENT == PATCH_ASSIGNMENT_COSTBASED
|
|
if( n_interactions_in_patch
|
|
!= global->patch_cost[patch->seq_no].n_total_inter )
|
|
{
|
|
printf( "Error: patch(%d) Inter counted: %d (n_total_inter %d)\n",
|
|
patch->seq_no,
|
|
n_interactions_in_patch,
|
|
global->patch_cost[patch->seq_no].n_total_inter ) ;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void get_elem_stat(Element *elem, long dummy, long process_id)
|
|
{
|
|
Interaction *pi ;
|
|
long p_visible = 0 ;
|
|
long c_visible = 0 ;
|
|
long i_visible = 0 ;
|
|
long match0, match1, match2, match3 ;
|
|
|
|
n_elements_in_patch++ ;
|
|
|
|
while( elem->area < min_elem_area )
|
|
{
|
|
min_elem_area *= 0.25 ;
|
|
n_equiv_elem_in_patch *= 4 ;
|
|
}
|
|
|
|
/* Classify visibility */
|
|
n_interactions_in_patch += elem->n_interactions ;
|
|
for( pi = elem->interactions ; pi ; pi = pi->next )
|
|
{
|
|
if( pi->visibility == 0.0 )
|
|
i_visible++ ;
|
|
else if( pi->visibility == 1.0 )
|
|
c_visible++ ;
|
|
else
|
|
p_visible++ ;
|
|
}
|
|
if( i_visible + c_visible + p_visible != elem->n_interactions )
|
|
printf( "Fatal: Interactions count miss match\n" ) ;
|
|
if( elem->n_vis_undef_inter != 0 )
|
|
printf( "Fatal: Visibility undef list count non zero(%ld)\n",
|
|
elem->n_vis_undef_inter ) ;
|
|
if( elem->vis_undef_inter != 0 )
|
|
printf( "Fatal: Visibility undef list not empty\n" ) ;
|
|
|
|
n_comp_visible_interactions += c_visible ;
|
|
n_invisible_interactions += i_visible ;
|
|
|
|
|
|
/* Count interactions / element */
|
|
if( elem->n_interactions > MAX_INTERACTION_PER_ELEMENT )
|
|
{
|
|
many_interaction.count++ ;
|
|
many_interaction.area += elem->area ;
|
|
}
|
|
else
|
|
{
|
|
elem_interaction[ elem->n_interactions ].count++ ;
|
|
elem_interaction[ elem->n_interactions ].area += elem->area ;
|
|
}
|
|
|
|
/* Analyze object coherence */
|
|
if( ! LEAF_ELEMENT( elem ) )
|
|
{
|
|
match0 = match1 = match2 = match3 = 0 ;
|
|
|
|
count_interaction(elem->center, elem->top, elem->right, elem->left,
|
|
&match3, &match2, &match1, &match0, process_id ) ;
|
|
count_interaction(elem->top, elem->right, elem->left, elem->center,
|
|
&match3, &match2, &match1, &match0, process_id ) ;
|
|
count_interaction(elem->right, elem->left, elem->center, elem->top,
|
|
&match3, &match2, &match1, &match0, process_id ) ;
|
|
count_interaction(elem->left, elem->center, elem->top, elem->right,
|
|
&match3, &match2, &match1, &match0, process_id ) ;
|
|
|
|
total_match3 += match3 ;
|
|
total_match2 += match2 ;
|
|
total_match1 += match1 ;
|
|
total_match0 += match0 ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void count_interaction(Element *es, Element *e1, Element *e2, Element *e3, long *c3, long *c2, long *c1, long *c0, long process_id)
|
|
{
|
|
Interaction *pi ;
|
|
long occurrence ;
|
|
|
|
for( pi = es->interactions ; pi ; pi = pi->next )
|
|
{
|
|
occurrence = search_intearction( e1->interactions, pi, process_id ) ;
|
|
occurrence += search_intearction( e2->interactions, pi, process_id ) ;
|
|
occurrence += search_intearction( e3->interactions, pi, process_id ) ;
|
|
switch( occurrence )
|
|
{
|
|
case 0: (*c0)++ ; break ;
|
|
case 1: (*c1)++ ; break ;
|
|
case 2: (*c2)++ ; break ;
|
|
case 3: (*c3)++ ; break ;
|
|
}
|
|
}
|
|
}
|
|
|
|
long search_intearction(Interaction *int_list, Interaction *inter, long process_id)
|
|
{
|
|
while( int_list )
|
|
{
|
|
if( int_list->destination == inter->destination )
|
|
return( 1 ) ;
|
|
|
|
int_list = int_list->next ;
|
|
}
|
|
|
|
return( 0 ) ;
|
|
}
|
|
|
|
/***************************************
|
|
*
|
|
* Prinit running time
|
|
*
|
|
****************************************/
|
|
|
|
void print_running_time(long process_id)
|
|
{
|
|
long time_diff, time_diff1 ;
|
|
|
|
time_diff = time_rad_end - time_rad_start ;
|
|
time_diff1 = time_rad_end - timing[0]->rad_start;
|
|
if( time_diff < 0 )
|
|
time_diff += CLOCK_MAX_VAL ;
|
|
if( time_diff1 < 0 )
|
|
time_diff1 += CLOCK_MAX_VAL ;
|
|
|
|
printf( "\tOverall start time\t%20lu\n", time_rad_start);
|
|
printf( "\tOverall end time\t%20lu\n", time_rad_end);
|
|
printf( "\tTotal time with initialization\t%20lu\n", time_diff);
|
|
printf( "\tTotal time without initialization\t%20lu\n", time_diff1);
|
|
}
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* Print process creation overhead
|
|
*
|
|
****************************************/
|
|
|
|
void print_fork_time(long process_id)
|
|
{
|
|
long pid ;
|
|
|
|
if( n_processors <= 1 )
|
|
return ;
|
|
|
|
printf( "\tProcess fork overhead\n" ) ;
|
|
for( pid = 0 ; pid < n_processors-1 ; pid++ )
|
|
{
|
|
printf( "\t Process %ld %.2f mS\n",
|
|
pid,
|
|
(timing[pid]->rad_start - time_rad_start) / 1000.0 ) ;
|
|
}
|
|
|
|
printf( "\t (total) %.2f mS\n",
|
|
(time_process_start[n_processors-2] - time_rad_start) / 1000.0 ) ;
|
|
}
|
|
|
|
|
|
/***************************************
|
|
*
|
|
* Initialize statistical info
|
|
*
|
|
****************************************/
|
|
|
|
void init_stat_info(long process_id)
|
|
{
|
|
long pid ;
|
|
long i ;
|
|
StatisticalInfo *ps ;
|
|
|
|
for( pid = 0 ; pid < MAX_PROCESSORS ; pid++ )
|
|
{
|
|
ps = &global->stat_info[ pid ] ;
|
|
ps->total_modeling_tasks = 0 ;
|
|
ps->total_def_patch_tasks = 0 ;
|
|
ps->total_ff_ref_tasks = 0 ;
|
|
ps->total_ray_tasks = 0 ;
|
|
ps->total_radavg_tasks = 0 ;
|
|
ps->total_interaction_comp = 0 ;
|
|
ps->total_visibility_comp = 0 ;
|
|
ps->partially_visible = 0 ;
|
|
ps->total_ray_intersect_test= 0 ;
|
|
ps->total_patch_cache_check = 0 ;
|
|
ps->total_patch_cache_hit = 0 ;
|
|
|
|
for( i = 0 ; i < PATCH_CACHE_SIZE ; i++ )
|
|
ps->patch_cache_hit[i] = 0 ;
|
|
|
|
for( i = 0 ; i < MAX_ITERATION_INFO ; i++ )
|
|
{
|
|
ps->per_iteration[ i ].visibility_comp = 0 ;
|
|
ps->per_iteration[ i ].ray_intersect_test = 0 ;
|
|
ps->per_iteration[ i ].tasks_from_myq = 0 ;
|
|
ps->per_iteration[ i ].tasks_from_otherq = 0 ;
|
|
ps->per_iteration[ i ].process_tasks_wait = 0 ;
|
|
ps->per_iteration[ i ].last_pr_task = 0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
*
|
|
* clear_radiosity()
|
|
*
|
|
***********************************************************/
|
|
|
|
|
|
void clear_radiosity(long process_id)
|
|
{
|
|
foreach_patch_in_bsp( clear_patch_radiosity, 0, 0 ) ;
|
|
}
|
|
|
|
|
|
void clear_patch_radiosity(Patch *patch, long dummy, long process_id)
|
|
{
|
|
foreach_element_in_patch( patch, clear_element_radiosity, 0, process_id ) ;
|
|
}
|
|
|
|
|
|
static void clear_element_radiosity(Element *elem, long dummy, long process_id)
|
|
{
|
|
elem->rad.r = 0 ;
|
|
elem->rad.g = 0 ;
|
|
elem->rad.b = 0 ;
|
|
|
|
elem->rad_subtree.r = 0 ;
|
|
elem->rad_subtree.g = 0 ;
|
|
elem->rad_subtree.b = 0 ;
|
|
|
|
global->prev_total_energy = global->total_energy ;
|
|
global->total_energy.r = 0 ;
|
|
global->total_energy.g = 0 ;
|
|
global->total_energy.b = 0 ;
|
|
}
|