diff --git a/commonb.c b/commonb.c index a106ccb..2617414 100644 --- a/commonb.c +++ b/commonb.c @@ -1495,20 +1495,13 @@ unsigned long max_mem ( return (MAX_MEM); } -/* Return memory (in MB) now available for a variable usage thread. */ -/* This routine takes into account the memory used by other workers. */ +/* Can we get "lots of memory", whatever that means? (Rules, slot counts) */ -int avail_mem ( - int thread_num, - unsigned long minimum_memory, /* If this much memory (in MB) can be returned without restarting other workers, then do so */ - unsigned long desired_memory, /* If this much memory (in MB) can be returned without restarting other workers, then do so */ - unsigned int *memory) /* Returned available memory, in MB */ +int avail_mem_qualitative ( + int thread_num) /* Returned available memory, in MB */ { - int i, fixed_threads[MAX_NUM_WORKERS]; - unsigned long fixed_usage, variable_usage, num_variable_threads, avail, diff; - + int lots_occupied = 0; /* Check if we are in a period of forced low memory usage */ - if (is_LowMemWhileRunning_active (thread_num)) { MEM_RESTART_FLAGS[thread_num] |= MEM_RESTART_LOWMEM_ENDS; return (STOP_NOT_ENOUGH_MEM); @@ -1522,19 +1515,37 @@ int avail_mem ( return (STOP_NOT_ENOUGH_MEM); } -/* Obtain lock before accessing memory global variables */ +/* Check if we must wait for more memory to become available. This happens when we reach the maximum allowable number of threads using a lot of memory. */ gwmutex_lock (&MEM_MUTEX); + lots_occupied = are_threads_using_lots_of_memory (thread_num); + gwmutex_unlock (&MEM_MUTEX); -/* Check if we must wait for more memory to become available. This happens when we reach the maximum allowable number of threads using a lot of memory. */ - - if (are_threads_using_lots_of_memory (thread_num)) { + if (lots_occupied) { MEM_RESTART_FLAGS[thread_num] |= MEM_RESTART_TOO_MANY_HIGHMEM; - gwmutex_unlock (&MEM_MUTEX); OutputStr (thread_num, "Exceeded limit on number of workers that can use lots of memory.\n"); return (STOP_NOT_ENOUGH_MEM); } + return (0); +} + +/* Return memory (in MB) now available for a variable usage thread. */ +/* This routine takes into account the memory used by other workers. */ + +int avail_mem ( + int thread_num, + unsigned long minimum_memory, /* If this much memory (in MB) can be returned without restarting other workers, then do so */ + unsigned long desired_memory, /* If this much memory (in MB) can be returned without restarting other workers, then do so */ + unsigned int *memory) /* Returned available memory, in MB */ +{ + int i, fixed_threads[MAX_NUM_WORKERS]; + unsigned long fixed_usage, variable_usage, num_variable_threads, avail, diff; + +/* Obtain lock before accessing memory global variables */ + + gwmutex_lock (&MEM_MUTEX); + /* Set flag saying this will be a variable usage thread. Remember the */ /* "good enough" value as it will be helpful in determining the best */ /* value this routine should return (for this thread and other threads) */ diff --git a/ecm.cpp b/ecm.cpp index 38ffdbb..b54597e 100644 --- a/ecm.cpp +++ b/ecm.cpp @@ -7806,6 +7806,13 @@ replan: unsigned long best_fftlen; best_fails = 0; best_poly_efficiency = 0.0; msgbuf[0] = 0; + + stop_reason = avail_mem_qualitative(thread_num); + if (stop_reason) { + if (ecmdata.state == ECM_STATE_MIDSTAGE) ecm_save (&ecmdata); + goto exit; + } + for (bool found_best = FALSE; ; ) { /* Initialize the polymult library (needed for calling polymult_mem_required). Let user override polymult tuning parameters. */ @@ -12333,6 +12340,13 @@ replan: unsigned long best_fftlen; best_fails = 0; best_poly_efficiency = 0.0; msgbuf[0] = 0; + + stop_reason = avail_mem_qualitative(thread_num); + if (stop_reason) { + if (pm1data.state == PM1_STATE_MIDSTAGE) pm1_save (&pm1data); + goto exit; + } + //GW: Can we get here (old save files) with V set and one of x or invx not set? If so, switching is an issue unless we convert V to binary. for (bool found_best = FALSE; ; ) { @@ -14918,7 +14932,7 @@ int pp1_stage2_impl ( min_memory = 1 + cvt_gwnums_to_mem (&pp1data->gwdata, 8); if (pp1data->state < PP1_STATE_STAGE2) desired_memory = 3 + cvt_gwnums_to_mem (&pp1data->gwdata, 144); else desired_memory = (unsigned int) (pp1data->pairmap_size >> 20) + cvt_gwnums_to_mem (&pp1data->gwdata, pp1data->stage2_numvals); - stop_reason = avail_mem (pp1data->thread_num, min_memory, desired_memory, &memory); + stop_reason = avail_mem_qualitative (pp1data->thread_num) || avail_mem (pp1data->thread_num, min_memory, desired_memory, &memory); if (stop_reason) return (stop_reason); /* Factor in the multiplier that we set to less than 1.0 when we get unexpected memory allocation errors. */