Commit 3df6433e authored by SOLIMAN Sylvain's avatar SOLIMAN Sylvain
Browse files

merge feature/openmpi

parents a15bbf39 f79b5971
......@@ -32,8 +32,9 @@ compile_cpp_program(SourceFiles, Options, ExecutableFilename) :-
;
CXX = 'g++'
),
setenv('OMPI_MPICXX', CXX),
compile_program(
CXX, SourceFiles,
'mpicxx', SourceFiles,
%FF no warning of deprecated PPL code
% ['--std=c++11', '-Dtypeof(x)=decltype(x)' | Options],
['-w', '--std=c++11', '-Dtypeof(x)=decltype(x)' | Options],
......@@ -41,7 +42,7 @@ compile_cpp_program(SourceFiles, Options, ExecutableFilename) :-
).
%% TODO
%% TODO
%% - robust parsing (w.r.t. spaces for instance)
%% - error handling (unknown library)
pkg_compile_options(PkgName, Options) :-
......
......@@ -132,7 +132,7 @@ ctl(E) :-
:- doc('\\emphright{steady(f) is a shorthand for EG(f)}').
:- doc('\\emphright{stable(f) is a shorthand for AG(f)}').
:- doc('\\emphright{checkpoint(f, g) is a shorthand for not EU(not f, g)). Note that such a factual property does not imply any causality relationship from f to g.}').
:- doc('\\emphright{checkpoint2(f, g) is a shorthand for not(g)/\\\\ EF(g)/\\\\checkpoint(f,g)}').
:- doc('\\emphright{checkpoint2(f, g) is a shorthand for not(g)/\\\\ EF(g)/\\\\checkpoint(f,g)}').
:- doc('\\emphright{oscil2(f) is a shorthand for EU(not(f), f /\\\\ EU(f, not(f) /\\\\ EU(not(f), f))) which is true if f has at least two peaks on one path}').
:- doc('\\emphright{oscil3(f) is a shorthand for EU(not(f), f /\\\\ EU(f, not(f) /\\\\ EU(not(f), f /\\\\ EU(f, not(f) /\\\\ EU(not(f), f))))) which is true if f has at least three peaks on one path}').
:- doc('\\emphright{oscil(f) is a shorthand for oscil3(f) /\\\\ EG(EF(f) /\\\\ EF(not f)) which is a necessary (not sufficient) condition for infinite oscillations in CTL}').
......
......@@ -26,7 +26,7 @@ then
}
brew tap brewsci/science
brewlings='swi-prolog gsl gnuplot graphviz pkg-config ppl libsbml nusmv node'
brewlings='swi-prolog gsl gnuplot graphviz pkg-config ppl libsbml nusmv node open-mpi'
for brewling in $brewlings ; do
install_or_upgrade "$brewling"
done
......@@ -39,7 +39,7 @@ then
### Ubuntu or Debian
sudo apt-get -qy update
sudo apt-get -qy install lsb-release curl gcc g++ make pkg-config libgsl0-dev gnuplot libppl-dev graphviz-dev git nodejs npm
sudo apt-get -qy install lsb-release curl gcc g++ make pkg-config libgsl0-dev gnuplot libppl-dev graphviz-dev git nodejs npm openmpi-bin libopenmpi-dev
release=$(lsb_release -sc)
......
......@@ -13,14 +13,7 @@
#include "domain_distance.inc"
#include "filter.inc"
// shared-memory parallelism for free
#if defined(_OPENMP)
#include <omp.h>
#else
typedef int omp_int_t;
inline omp_int_t omp_get_thread_num() { return 0; }
inline omp_int_t omp_get_max_threads() { return 1; }
#endif
#include <mpi.h>
static double
satisfaction_degree(gsl_solver *solver, gsl_solver_config *config, double values[DIMENSION])
......@@ -49,19 +42,15 @@ satisfaction_degree(gsl_solver *solver, gsl_solver_config *config, double values
gsl_solver_iterate(&state, &table);
free_gsl_solver_state(&state);
// FIXME cannot use OpenMP to parallelize PPL
#pragma omp critical(ppl)
{
PPL::set_rounding_for_PPL();
domain = (*compute_condition_domain[0])(table);
/* using PPL::IO_Operators::operator<<; */
/* std::cerr << domain << "." << std::endl; */
/* std::cerr << j << " rows" << std::endl; */
// Ignore negative distances for robustness computation
max_distance = std::max(0.0, domain_distance(domain, 0));
/* std::cerr << "distance " << max_distance << std::endl; */
PPL::restore_pre_PPL_rounding();
}
PPL::set_rounding_for_PPL();
domain = (*compute_condition_domain[0])(table);
/* using PPL::IO_Operators::operator<<; */
/* std::cerr << domain << "." << std::endl; */
/* std::cerr << j << " rows" << std::endl; */
// Ignore negative distances for robustness computation
max_distance = std::max(0.0, domain_distance(domain, 0));
/* std::cerr << "distance " << max_distance << std::endl; */
PPL::restore_pre_PPL_rounding();
return 1/(1 + max_distance);
}
......@@ -80,43 +69,68 @@ main(int argc, char *argv[])
std::normal_distribution<double> distribution[DIMENSION];
int i, j;
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
double robustness_mean = 0, relative_robustness_error;
double robustness_ssd = 0, delta, delta2, new_value;
gsl_solver_config config[omp_get_max_threads()];
gsl_solver solver[omp_get_max_threads()];
#pragma omp parallel for
for (i = 0; i < omp_get_max_threads(); i++) {
init_gsl_solver_config(&config[i]);
init_gsl_solver(&solver[i], &config[i]);
}
double robustness_mean = 0, new_value;
// double robustness_ssd = 0, delta, delta2, relative_robustness_error;
gsl_solver_config config;
gsl_solver solver;
int loc_samples;
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// fprintf(stderr, "proc %d of %d\n", world_rank, world_size);
// Different seed on each processor
generator.seed(SEED*(world_rank + 1));
init_gsl_solver_config(&config);
init_gsl_solver(&solver, &config);
for (i = 0; i < DIMENSION; i++) {
const struct search_parameter *param = &search_parameters[i];
/* fprintf(stderr, "param %d init %g\n", i, param->init); */
// fprintf(stderr, "param %d init %g\n", i, param->init);
distribution[i] = std::normal_distribution<double>(param->init, COEFF_VAR*param->init);
}
for (j = 0; j < SAMPLES; ++j) {
#pragma omp parallel for
if (world_rank == 0) {
loc_samples = (int) SAMPLES / world_size + SAMPLES % world_size;
} else {
loc_samples = (int) SAMPLES / world_size;
}
// fprintf(stderr, "proc %d handling %d samples\n", world_rank, loc_samples);
new_value = 0;
for (j = 0; j < loc_samples; ++j) {
for (i = 0; i < DIMENSION; i++) {
population[i] = distribution[i](generator);
}
new_value = satisfaction_degree(&solver[omp_get_thread_num()], &config[omp_get_thread_num()], population);
delta = new_value - robustness_mean;
robustness_mean += delta/(j+1);
delta2 = new_value - robustness_mean;
robustness_ssd += delta*delta2;
new_value += satisfaction_degree(&solver, &config, population);
// NOTE removed in favor of MPI parallel code
// delta = new_value - robustness_mean;
// robustness_mean += delta/(j+1);
// delta2 = new_value - robustness_mean;
// robustness_ssd += delta*delta2;
// https://en.wikipedia.org/wiki/Monte_Carlo_integration
// https://en.wikipedia.org/wiki/Variance#Population_variance_and_sample_variance
relative_robustness_error = sqrt(robustness_ssd)/((j+1)*robustness_mean);
/* fprintf(stderr, "%d: %g %g\n", j, robustness_mean, relative_robustness_error); */
if (j > SAMPLES*RELATIVE_ROBUSTNESS_ERROR &&
relative_robustness_error < RELATIVE_ROBUSTNESS_ERROR) {
break;
}
// relative_robustness_error = sqrt(robustness_ssd)/((j+1)*robustness_mean);
// fprintf(stderr, "%d: %g %g\n", j, robustness_mean, relative_robustness_error);
// if (j > SAMPLES*RELATIVE_ROBUSTNESS_ERROR &&
// relative_robustness_error < RELATIVE_ROBUSTNESS_ERROR) {
// break;
// }
}
printf("%f\n", robustness_mean);
#pragma omp parallel for
for (i = 0; i < omp_get_max_threads(); i++) {
free_gsl_solver(&solver[i]);
// fprintf(stderr, "proc %d total robustness %f\n", world_rank, new_value);
MPI_Reduce(&new_value, &robustness_mean, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if (world_rank == 0) {
// fprintf(stderr, "proc %d sum of robustness %f\n", world_rank, robustness_mean);
robustness_mean = robustness_mean / SAMPLES;
printf("%f\n", robustness_mean);
}
free_gsl_solver(&solver);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
return EXIT_SUCCESS;
}
......@@ -11,14 +11,7 @@
#include "domain_distance.inc"
#include "filter.inc"
// shared-memory parallelism for free
#if defined(_OPENMP)
#include <omp.h>
#else
typedef int omp_int_t;
inline omp_int_t omp_get_thread_num() { return 0; }
inline omp_int_t omp_get_max_threads() { return 1; }
#endif
#include <mpi.h>
static double
fitfun(gsl_solver *solver, gsl_solver_config *config, double values[DIMENSION])
......@@ -68,18 +61,14 @@ fitfun(gsl_solver *solver, gsl_solver_config *config, double values[DIMENSION])
gsl_solver_iterate(&state, &table);
free_gsl_solver_state(&state);
// FIXME cannot use OpenMP to parallelize PPL
#pragma omp critical(ppl)
{
PPL::set_rounding_for_PPL();
domain = (*compute_condition_domain[i])(table);
/* using PPL::IO_Operators::operator<<; */
/* std::cerr << domain << "." << std::endl; */
/* std::cerr << j << " rows" << std::endl; */
max_distance = std::max(max_distance, domain_distance(domain, i));
/* std::cerr << "distance " << max_distance << std::endl; */
PPL::restore_pre_PPL_rounding();
}
PPL::set_rounding_for_PPL();
domain = (*compute_condition_domain[i])(table);
/* using PPL::IO_Operators::operator<<; */
/* std::cerr << domain << "." << std::endl; */
/* std::cerr << j << " rows" << std::endl; */
max_distance = std::max(max_distance, domain_distance(domain, i));
/* std::cerr << "distance " << max_distance << std::endl; */
PPL::restore_pre_PPL_rounding();
}
result += max_distance;
......@@ -96,75 +85,134 @@ main(int argc, char *argv[])
int i;
/* int j; */
int lambda;
gsl_solver_config config[omp_get_max_threads()];
gsl_solver solver[omp_get_max_threads()];
#pragma omp parallel for
for (i = 0; i < omp_get_max_threads(); i++) {
init_gsl_solver_config(&config[i]);
init_gsl_solver(&solver[i], &config[i]);
}
gsl_solver_config config;
gsl_solver solver;
double best_vd = 1;
for (i = 0; i < DIMENSION; i++) {
const struct search_parameter *param = &search_parameters[i];
double min = param->min;
double max = param->max;
xstart[i] = param->init;
stddev[i] = (max - min) / 2;
}
arFunvals = cmaes_init(
&evo, DIMENSION, xstart, stddev, SEED, 0, "cmaes_initials.par");
cmaes_ReadSignals(&evo, "cmaes_signals.par");
evo.sp.stStopFitness.flg = 1;
evo.sp.stStopFitness.val = STOPFIT;
// somehow still have to test for best_vd, not sure why...
lambda = cmaes_Get(&evo, "lambda");
while(!cmaes_TestForTermination(&evo) && best_vd >= STOPFIT) {
pop = cmaes_SamplePopulation(&evo);
#pragma omp parallel for
for (i = 0; i < lambda; ++i) {
arFunvals[i] = fitfun(&solver[omp_get_thread_num()], &config[omp_get_thread_num()], pop[i]);
/* fprintf(stderr, "distance: %f\n", arFunvals[i]); */
/* for (j = 0; j < DIMENSION; ++j) { */
/* fprintf(stderr, " %.17g\n", pop[i][j]); */
/* } */
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// fprintf(stderr, "proc %d of %d\n", world_rank, world_size);
MPI_Request req;
init_gsl_solver_config(&config);
init_gsl_solver(&solver, &config);
if (world_rank != 0) {
double data[DIMENSION];
double fit;
MPI_Status status;
int amount;
while(true) {
// fprintf(stderr, "proc %d ready\n", world_rank);
MPI_Recv(&data, DIMENSION, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_DOUBLE, &amount);
if (amount == DIMENSION) {
// fprintf(stderr, "proc %d received\n", world_rank);
fit = fitfun(&solver, &config, data);
// fprintf(stderr, "proc %d sending %f\n", world_rank, fit);
MPI_Isend(&fit, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &req);
MPI_Request_free(&req);
} else {
// fprintf(stderr, "proc %d terminating\n", world_rank);
break;
}
}
cmaes_UpdateDistribution(&evo, arFunvals);
best_vd = cmaes_Get(&evo, "fbestever");
/* fprintf(stderr, "Best satisfaction degree: %f\n", */
/* 1 / (1 + best_vd)); */
/* xfinal = cmaes_GetNew(&evo, "xbestever"); */
/* for (i = 0; i < DIMENSION; i++) { */
/* fprintf(stderr, " %f\n", xfinal[i]); */
/* } */
cmaes_ReadSignals(&evo, "cmaes_signals.par");
fflush(stdout);
}
cmaes_WriteToFile(&evo, "all", "allcmaes.dat");
if (cmaes_TestForTermination(&evo)) {
char reason[3024];
strncpy(reason, cmaes_TestForTermination(&evo), 3024);
strtok(reason, "\n");
printf("%s\n", reason);
} else {
printf("Biocham stop with best fitness %g < stop fitness %g\n",
best_vd, STOPFIT);
}
xfinal = cmaes_GetNew(&evo, "xbestever");
for (i = 0; i < DIMENSION; i++) {
/* fprintf(stderr, "%.17g\n", xfinal[i]); */
if (LOGNORMAL) {
printf("%.17g\n", exp(xfinal[i]));
for (i = 0; i < DIMENSION; i++) {
const struct search_parameter *param = &search_parameters[i];
double min = param->min;
double max = param->max;
xstart[i] = param->init;
stddev[i] = (max - min) / 2;
}
arFunvals = cmaes_init(
&evo, DIMENSION, xstart, stddev, SEED, 0, "cmaes_initials.par");
cmaes_ReadSignals(&evo, "cmaes_signals.par");
evo.sp.stStopFitness.flg = 1;
evo.sp.stStopFitness.val = STOPFIT;
// somehow still have to test for best_vd, not sure why...
lambda = cmaes_Get(&evo, "lambda");
// fprintf(stderr, "population size %d spread on %d procs\n", lambda, world_size);
while(!cmaes_TestForTermination(&evo) && best_vd >= STOPFIT) {
pop = cmaes_SamplePopulation(&evo);
// Send all in a non-blocking way
for (i = 0; i < lambda; ++i) {
if (i % world_size != 0) {
// fprintf(stderr, "proc %d sending to %d\n", world_rank, i % world_size);
MPI_Isend(pop[i], DIMENSION, MPI_DOUBLE, i % world_size, 0, MPI_COMM_WORLD, &req);
MPI_Request_free(&req);
}
}
// Do all locally
for (i=0; i < lambda; ++i) {
if (i % world_size == 0) {
arFunvals[i] = fitfun(&solver, &config, pop[i]);
// fprintf(stderr, "proc %d computing locally\n", world_rank, arFunvals[i]);
}
}
// Wait for all results
for (i=0; i < lambda; ++i) {
if (i% world_size != 0) {
// fprintf(stderr, "proc %d waiting for %d\n", world_rank, i % world_size);
MPI_Recv(&arFunvals[i], 1, MPI_DOUBLE, i % world_size, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
// fprintf(stderr, "proc %d received %f from %d\n", world_rank, arFunvals[i], i % world_size);
}
/* fprintf(stderr, "distance: %f\n", arFunvals[i]); */
/* for (j = 0; j < DIMENSION; ++j) { */
/* fprintf(stderr, " %.17g\n", pop[i][j]); */
/* } */
}
// fprintf(stderr, "proc %d finished one loop\n", world_rank);
cmaes_UpdateDistribution(&evo, arFunvals);
best_vd = cmaes_Get(&evo, "fbestever");
/* fprintf(stderr, "Best satisfaction degree: %f\n", */
/* 1 / (1 + best_vd)); */
/* xfinal = cmaes_GetNew(&evo, "xbestever"); */
/* for (i = 0; i < DIMENSION; i++) { */
/* fprintf(stderr, " %f\n", xfinal[i]); */
/* } */
cmaes_ReadSignals(&evo, "cmaes_signals.par");
fflush(stdout);
}
else {
printf("%.17g\n", xfinal[i]);
for (i=1; i < world_size; i++) {
// send end message
MPI_Send(&best_vd, 0, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
}
// fprintf(stderr, "proc %d done\n", world_rank);
cmaes_WriteToFile(&evo, "all", "allcmaes.dat");
if (cmaes_TestForTermination(&evo)) {
char reason[3024];
strncpy(reason, cmaes_TestForTermination(&evo), 3024);
strtok(reason, "\n");
printf("%s\n", reason);
} else {
printf("Biocham stop with best fitness %g < stop fitness %g\n",
best_vd, STOPFIT);
}
xfinal = cmaes_GetNew(&evo, "xbestever");
for (i = 0; i < DIMENSION; i++) {
/* fprintf(stderr, "%.17g\n", xfinal[i]); */
if (LOGNORMAL) {
printf("%.17g\n", exp(xfinal[i]));
}
else {
printf("%.17g\n", xfinal[i]);
}
}
printf("%f\n", 1 / (1 + best_vd));
cmaes_exit(&evo);
free(xfinal);
}
printf("%f\n", 1 / (1 + best_vd));
cmaes_exit(&evo);
free(xfinal);
#pragma omp parallel for
for (i = 0; i < omp_get_max_threads(); i++) {
free_gsl_solver(&solver[i]);
}
free_gsl_solver(&solver);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
return EXIT_SUCCESS;
}
......@@ -23,7 +23,7 @@ search_condition((Formula, Event, Objective)) :-
:- doc('The continuous satisfaction degree of an FO-LTL(Rlin) in a given trace with respect to the objective values for the free variables can be used to compute parameter sensitivity indices and robustness measures with respect to parameter perturbation according to normal distributions, and to search parameter values for satisfying an FO-LTL(Rlin) formula \\cite{RBFS11tcs} or even maximizing the margins and the robustness \\cite{FS18cmsb}.').
:- initial('option(robustness_samples: 100)').
:- initial('option(robustness_relative_error: 0.05)').
:- initial('option(openmpi_procs: 0)').
:- initial('option(robustness_coeff_var: 0.1)').
......@@ -47,10 +47,10 @@ robustness(Formula, Parameters, Objective) :-
'number of samples used for averaging'
),
option(
robustness_relative_error,
number,
RelativeError,
'relative sampling error used to stop estimation of the robustness'
openmpi_procs,
integer,
NProc,
'Number of processors to use with OpenMPI (0 for auto).'
),
option(
error_epsilon_absolute, number, _ErrorEpsilonAbsolute,
......@@ -98,7 +98,7 @@ biocham: robustness(G(Time < T => a > b), [k], [T -> 5]).
numerical_simulation:conditional_event/2
],
robustness_aux(Parameters, [(Formula, [], Objective)], Samples,
RelativeError, Variation)
NProc, Variation)
)
).
......@@ -151,6 +151,12 @@ search_parameters(Formula, Parameters, Objective) :-
'stop when distance to the objective is less than this value (use 0 by default and
negative values in [-1,0] to maximize margins)'
),
option(
openmpi_procs,
integer,
_NProc,
'Number of processors to use with OpenMPI (0 for auto).'
),
doc('
tries to satisfy a FO-LTL(Rlin) constraint by varying the parameters listed
in \\argument{Parameters}.
......@@ -225,6 +231,12 @@ search_parameters(Parameters, Conditions) :-
'stop when distance to the objective is less than this value (use
negative to enforce robustness)'
),
option(
openmpi_procs,
integer,
_NProc,
'Number of processors to use with OpenMPI (0 for auto).'
),
doc('similar to \\command{search_parameters/3} but uses the list of
\\argument{Conditions} as triples with an FOLTL formula, a list of parameters instantiations (e.g. describing a mutant), and an objective for the
variables of the formula.
......@@ -272,7 +284,7 @@ search_parameters_aux(Parameters, Conditions, Result) :-
populate_field_columns(Options),
with_output_to_file(DomainCFilename,
forall(
nth0(Index, Conditions, (Formula, _, _)),
nth0(Index, Conditions, (Formula, _, _)),
(
expand_formula(Formula, ExpandedFormula),
atom_number(AIndex, Index),
......@@ -303,8 +315,16 @@ search_parameters_aux(Parameters, Conditions, Result) :-
)
),
compile_search_cpp_program(ExecutableFilename),
get_option(openmpi_procs, NProc),
(
NProc > 0
->
MPIArgs = ['-n', NProc, ExecutableFilename]
;
MPIArgs = [ExecutableFilename]
),
call_subprocess(
ExecutableFilename, [], [stdout(pipe(ResultStream))]
path('mpirun'), MPIArgs, [stdout(pipe(ResultStream))]
),
statistics(walltime, [_, MilliTime]),
Time is MilliTime / 1000,
......@@ -328,7 +348,7 @@ search_parameters_aux(Parameters, Conditions, Result) :-
% Prolog version of robustness computation for Prolog methods
robustness_aux(
ParameterList, [(Formula, [], Objective)], NSamples, _RelativeError,
ParameterList, [(Formula, [], Objective)], NSamples, _NProc,
VariationCoefficient
) :-
get_option(method, M),
......@@ -377,7 +397,7 @@ robustness_aux(
format('Time: ~p s\n', [Time]),
format('Robustness degree: ~p~n', [Degree]).
robustness_aux(ParameterList, Conditions, Samples, RelativeError, Variation) :-
robustness_aux(ParameterList, Conditions, Samples, NProc, Variation) :-
retractall(free_variable_index(_, _, _)),
GslCFilename = 'ode.inc',
DomainCFilename = 'check.inc',
......@@ -394,7 +414,7 @@ robustness_aux(ParameterList, Conditions, Samples, RelativeError, Variation) :-
populate_field_columns(Options),
with_output_to_file(DomainCFilename,
forall(
nth0(Index, Conditions, (Formula, _, _)),
nth0(Index, Conditions, (Formula, _, _)),
(
expand_formula(Formula, ExpandedFormula),
atom_number(AIndex, Index),
......@@ -419,15 +439,22 @@ robustness_aux(ParameterList, Conditions, Samples, RelativeError, Variation) :-
SearchParametersCFilename,
(
generate_random_seed,
generate_sample_number_and_var(Samples, RelativeError, Variation),
generate_sample_number_and_var(Samples, Variation),
generate_conditions(Conditions),
generate_search_parameters(Parameters),
generate_objective(Objectives)
)
),
compile_robustness_cpp_program(ExecutableFilename),
(
NProc > 0
->
MPIArgs = ['-n', NProc, ExecutableFilename]
;
MPIArgs = [ExecutableFilename]
),
call_subprocess(
ExecutableFilename, [], [stdout(pipe(ResultStream))]
path('mpirun'), MPIArgs, [stdout(pipe(ResultStream))]
),
statistics(walltime, [_, MilliTime]),
Time is MilliTime / 1000,
......@@ -489,9 +516,8 @@ generate_random_seed :-
format('#define SEED ~d~n', [NewSeed]).
generate_sample_number_and_var(Samples, RelativeError, Variation) :-
generate_sample_number_and_var(Samples, Variation) :-
format('#define SAMPLES ~d~n', [Samples]),
format('#define RELATIVE_ROBUSTNESS_ERROR ~p~n', [RelativeError]),
format('#define COEFF_VAR ~p~n', [Variation]).
......@@ -573,9 +599,8 @@ static const struct search_parameter search_parameters[DIMENSION] = {\n'),
compile_search_cpp_program(ExecutableFilename) :-
gsl_compile_options(GslCompileOptions),
ppl_compile_options(PplCompileOptions),
openmp_compile_options(OmpCompileOptions),
flatten(
[GslCompileOptions, PplCompileOptions, OmpCompileOptions],
[GslCompileOptions, PplCompileOptions],
AllCompileOptions
),
compile_cpp_program(
......@@ -588,9 +613,8 @@ compile_search_cpp_program(ExecutableFilename) :-
compile_robustness_cpp_program(ExecutableFilename) :-
gsl_compile_options(GslCompileOptions),
ppl_compile_options(PplCompileOptions),
openmp_compile_options(OmpCompileOptions),
flatten(
[GslCompileOptions, PplCompileOptions, OmpCompileOptions],
[GslCompileOptions, PplCompileOptions],
AllCompileOptions
),
compile_cpp_program(
......@@ -600,25 +624,6 @@ compile_robustness_cpp_program(ExecutableFilename) :-
).
% FIXME ugly hack to try and guess if we have openmp support
openmp_compile_options(OmpCompileOptions) :-
current_prolog_flag(arch, Arch),
(
sub_atom(Arch, _, 6, _, darwin)
->
(
getenv('CXX', CXX),
sub_atom(CXX, _, 1, _, '-')
->
OmpCompileOptions = ['-fopenmp']
;
OmpCompileOptions = []
)
;
OmpCompileOptions = ['-fopenmp']
).
ensure_parameters(Parameters) :-
forall(
member(Min <= Parameter <= _Max, Parameters),
......