COSC-4P82-Final-Project/lib/lilgp/bugs.html

224 lines
5.6 KiB
HTML

<HTML>
<HEAD>
<TITLE>
lil-gp Bug Patches
</TITLE>
</HEAD>
<BODY bgcolor=white>
<H1> lil-gp Bug Patches</h1>
<p> I have identified two chief bugs in lil-gpl 1.1 beta while working in multi-threaded mode. Until they are resolved, here are (ugly) patches to the code which should work nicely.
<a href="http://www.daimi.aau.dk/~ptr/">Peter Anderson</a> has also identified a bug in lilgp's ERC facility; I've not verified this bug, but his patch is located <a href="peters-patch.html">here</a>.
<h2>The Tree Evaluation Facility</h2>
<p> This appears to be a <b>very</b> serious bug; all the function <tt>set_current_individual()</tt> does is modify a global static pointer. This creates a very dangerous race condition when individuals are being evaluated simultaneously. The patch is to move this global variable into the thread-safe globaldata structure. This means you will have to first add to your <b>globaldata</b> structure the line...
<p><tt>individual* current_individual;</tt>
<p>You should not access this line in your evaluation code, even though it's in the globaldata structure. Once this line has been added, follow the following patch instructions.
<p><b>Open the file <tt>eval.c</tt>. Change the passage...</b>
<P><pre><tt>
static individual * current_individual;
void set_current_individual ( individual *ind )
{
current_individual = ind;
}
</tt></pre>
<p><b>...to...</b>
<p><pre><tt>
#if !defined(POSIX_MT) && !defined(SOLARIS_MT)
static individual * current_individual;
#define CURRENT_INDIVIDUAL current_individual
#else
#define CURRENT_INDIVIDUAL ((get_globaldata())->current_individual)
#endif
void set_current_individual ( individual *ind )
{
CURRENT_INDIVIDUAL = ind;
}
</tt></pre>
<p><b>...next, there are THREE passages you'll need to change. They're all identical. All three times it occurs, change...</b>
<p><pre><tt>
arg->d = evaluate_tree ( current_individual->tr[f->evaltree].data,
f->evaltree );
</tt></pre>
<p><b>...to...</b>
<p><pre><tt>
arg->d = evaluate_tree ( CURRENT_INDIVIDUAL->tr[f->evaltree].data,
f->evaltree );
</tt></pre>
<h2>The Random Facility</h2>
<p> lil-gp's random facility is not threadsafe and cannot be called from your evaluation code in multi-threaded mode without some patching. The patch for this wraps the random facility in a mutex so only one thread can call the random function at a time. Assuming threads aren't re-seeing the generator, the only function that needs to be wrapped is <tt>random_double()</tt> because the other random functions operate on it. <b>Note that this patch only works for POSIX Threads</b>. You'll have to code your own Solaris Threads patch, sorry. Here are the patch instructions.
<p><b>First open <tt>main.c</tt>, and change the passage</b>
<P><pre><tt>
/* maximum number of nodes per individual. -1 if no limit is
enforced. */
int ind_nodelimit;
int main ( int argc, char **argv )
{
multipop *mpop;
int startgen;
char *param;
event start, end, diff;
event eval, breed;
int startfromcheckpoint;
#ifdef MEMORY_LOG
/* dump all memory allocations to a file. */
mlog = fopen ( "memory.log", "w" );
#endif
</tt></pre>
<p> <b>...to...</b>
<p><pre><tt>
/* maximum number of nodes per individual. -1 if no limit is
enforced. */
int ind_nodelimit;
extern pthread_mutex_t random_mutex; /* Mutexes the random code */
int main ( int argc, char **argv )
{
multipop *mpop;
int startgen;
char *param;
event start, end, diff;
event eval, breed;
int startfromcheckpoint;
pthread_mutex_init(&random_mutex,NULL); /* Initialize the random mutex */
#ifdef MEMORY_LOG
/* dump all memory allocations to a file. */
mlog = fopen ( "memory.log", "w" );
#endif
</tt></pre>
<p><b> Then modify the passage (at the end of <tt>main()</tt>)...</b>
<p><pre><tt>
/* print memory/time statistics and close output files. */
output_system_stats ( &diff, &eval, &breed );
close_output_streams();
#ifdef MEMORY_LOG
fclose ( mlog );
#endif
/* all done. */
return 0;
}
</tt></pre>
<p><b>...to...</b>
<p><pre><tt>
/* print memory/time statistics and close output files. */
output_system_stats ( &diff, &eval, &breed );
close_output_streams();
#ifdef MEMORY_LOG
fclose ( mlog );
#endif
pthread_mutex_destroy(&random_mutex); /* Destroy random mutex */
/* all done. */
return 0;
}
</tt></pre>
<p><b> Next, open the file <tt>random.c</tt> Change the passage </b>
<p><pre><tt>
static double mz = 0.0;
static double ma[55]; /* the number 55 is special -- see Knuth. */
static int inext, inextp;
</tt></pre>
<p><b> ...to...</b>
<p><pre><tt>
static double mz = 0.0;
static double ma[55]; /* the number 55 is special -- see Knuth. */
static int inext, inextp;
pthread_mutex_t random_mutex;
</tt></pre>
<p><b> and change the function...</b>
<p><pre><tt>
double random_double ( void )
{
double mj;
double res;
inext = (inext+1)%55;
inextp = (inextp+1)%55;
mj = ma[inext] - ma[inextp];
if ( mj < mz )
mj = mj + mbig;
ma[inext] = mj;
res=mbig;
return mj/res;
}
</tt></pre>
<p><b> ...to...</b>
<p><pre><tt>
double random_double ( void )
{
/* There's a race condition on this, so we need to mutex it! */
double mj;
double res;
pthread_mutex_lock(&random_mutex);
inext = (inext+1)%55;
inextp = (inextp+1)%55;
mj = ma[inext] - ma[inextp];
if ( mj < mz )
mj = mj + mbig;
ma[inext] = mj;
res=mbig;
pthread_mutex_unlock(&random_mutex);
return mj/res;
}
</tt></pre>
</BODY>
</HTML>