commit fb07d7b9647fa30361039fea0260c373c57237e3
parent 0fece2374fdcc1b36fbc1f3d3665d61cc54fb3c3
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Wed, 3 Jun 2020 19:30:43 +0200
BugFix: invalid settings applied in multiline scenarii
Implement multithreaded execution over setting lines.
Diffstat:
11 files changed, 307 insertions(+), 71 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -56,6 +56,7 @@ configure_file(${GREEN_SOURCE_DIR}/green-version.h.in
###############################################################################
find_package(RCMake 0.4 REQUIRED)
find_package(RSys 0.9 REQUIRED)
+find_package(OpenMP 2.0 REQUIRED)
if(MSVC)
find_package(MuslGetopt REQUIRED)
endif()
@@ -116,11 +117,13 @@ add_executable(sgreen
if(CMAKE_COMPILER_IS_GNUCC)
set(MATH_LIB m)
set_target_properties(sgreen PROPERTIES
- COMPILE_FLAGS "-std=c99"
+ COMPILE_FLAGS "-std=c99 ${OpenMP_C_FLAGS}"
+ LINK_FLAGS "${OpenMP_C_FLAGS}"
VERSION ${GREEN_VERSION})
elseif(MSVC)
set(GETOPT_LIB MuslGetopt)
set_target_properties(sgreen PROPERTIES
+ COMPILE_FLAGS ${OpenMP_C_FLAGS}
VERSION ${GREEN_VERSION})
endif()
diff --git a/doc/sgreen.1.txt.in b/doc/sgreen.1.txt.in
@@ -53,7 +53,7 @@ simulated system.
OPTIONS
-------
*-a* _FILE_NAME_::
- Apply a Green function using the variable settings read in a file. Can only
+ Apply a Green function using the variable settings read from a file. Can only
be applied in conjunction with option *-g*.
*-e*::
diff --git a/src/green-args.c b/src/green-args.c
@@ -56,7 +56,7 @@ init_args
args->command_filename = NULL;
args->green_filename = NULL;
args->info_filename = NULL;
- args->nthreads = DEFAULT_NTHREADS;
+ args->nthreads = (unsigned)omp_get_num_procs();
args->verbose = GREEN_DEFAULT_VERBOSE_LEVEL;
}
diff --git a/src/green-args.h b/src/green-args.h
@@ -22,8 +22,6 @@ struct logger;
struct mem_allocator;
struct args;
-#define DEFAULT_NTHREADS UINT_MAX
-
struct args {
struct logger* logger;
struct mem_allocator* allocator;
diff --git a/src/green-compute.c b/src/green-compute.c
@@ -26,6 +26,7 @@
#include <math.h>
#include <string.h>
#include <ctype.h>
+#include <omp.h>
void
check_green_table_variables_use
@@ -69,14 +70,17 @@ check_green_table_variables_use
#define INSERT(Elt, Field) { \
struct variable_data vd___; \
- vd___.value = &green->table[Elt].Field ## _value; \
+ vd___.idx = ((Elt) * sizeof(struct applied_settings_elt) \
+ + offsetof(struct applied_settings_elt, Field ## _value)) / sizeof(double); \
vd___.used = (green->table[Elt].Field ## _weight != 0); \
vd___.unknown = green->table[Elt].Field ## _unknown; \
if(vd___.unknown) green->unknown_variables = 1; \
else if(!vd___.used) green->unused_variables = 1; \
- if(htable_variable_ptr_find(&green->variable_ptrs, &(green->table[Elt].Field ## _name))) \
- FATAL("Name already known"); \
- ERR(htable_variable_ptr_set(&green->variable_ptrs, &(green->table[Elt].Field ## _name), &vd___)); \
+ if(htable_variable_ptr_find(&green->variable_ptrs, \
+ &(green->table[Elt].Field ## _name))) \
+ FATAL("Name already known"); /* Should have been detected by stardis */ \
+ ERR(htable_variable_ptr_set(&green->variable_ptrs, \
+ &(green->table[Elt].Field ## _name), &vd___)); \
} (void)0
#define MK_VAR(Str) \
@@ -160,7 +164,7 @@ build_green_table
else if(desc->type == DESC_SOLID_FLUID_CONNECT) {
/* No variables here */
}
- else FATAL("Invalid desc type.");
+ else FATAL("Invalid desc type."); /* Should have been detected by stardis */
}
/* Ambient ID is desc_count */
ambient_id = green->counts.desc_count;
@@ -180,8 +184,21 @@ error:
#undef INSERT
static void
+applied_settings_set_defaults
+ (const struct green* green,
+ struct applied_settings_elt* settings)
+{
+ unsigned i;
+ FOR_EACH(i, 0, 1 + green->counts.desc_count) {
+ settings[i].end_value = green->table[i].end_value;
+ settings[i].other_value = green->table[i].other_value;
+ }
+}
+
+static void
green_compute_1
(const struct green* green,
+ const struct applied_settings_elt* settings,
double* E,
double* STD)
{
@@ -200,7 +217,7 @@ green_compute_1
|| DESC_IS_H(green->descriptions[id].type)
|| DESC_IS_MEDIUM(green->descriptions[id].type));
ASSERT(green->table[id].end_defined);
- Ti = green->table[id].end_value;
+ Ti = settings[id].end_value;
FOR_EACH(j, 0, sample->header.pw_count) {
const double w = sample->pw_weights[j];
@@ -208,7 +225,7 @@ green_compute_1
ASSERT(id < green->counts.desc_count);
ASSERT(DESC_IS_MEDIUM(green->descriptions[id].type));
ASSERT(green->table[id].other_defined);
- Ti += w * green->table[id].other_value;
+ Ti += w * settings[id].other_value;
}
FOR_EACH(j, 0, sample->header.fx_count) {
const double w = sample->fx_weights[j];
@@ -216,7 +233,7 @@ green_compute_1
ASSERT(id < green->counts.desc_count);
ASSERT(DESC_IS_F(green->descriptions[id].type));
ASSERT(green->table[id].other_defined);
- Ti += w * green->table[id].other_value;
+ Ti += w * settings[id].other_value;
}
T += Ti;
T2 += Ti * Ti;
@@ -230,7 +247,8 @@ static res_T
parse_line
(const char* file_name,
char* line,
- struct green* green)
+ struct green* green,
+ struct applied_settings_elt* settings)
{
res_T res = RES_OK;
struct str keep;
@@ -286,7 +304,7 @@ parse_line
logger_print(green->logger, LOG_WARNING, "In file '%s':\n", file_name);
logger_print(green->logger, LOG_WARNING, "%s\n", str_cget(&keep));
}
- ERR(cstr_to_double(tk, vd->value));
+ ERR(cstr_to_double(tk, ((double*)settings) + vd->idx));
name_count++;
}
@@ -304,50 +322,63 @@ error:
res_T
green_compute
(struct green* green,
- const char* in_name,
- const int mode,
- FILE* out_stream)
+ const char* in_name)
{
res_T res = RES_OK;
- struct txtrdr* txtrdr = NULL;
- FILE* stream = NULL;
- struct str keep;
- double E, STD;
+ size_t sz;
+ int64_t i;
+ struct applied_settings_elt** settings = NULL;
ASSERT(green && in_name);
+ sz = darray_line_size_get(&green->settings);
+ ASSERT(sz < INT64_MAX);
- str_init(green->allocator, &keep);
- stream = fopen(in_name, "r");
- if(!stream) {
- logger_print(green->logger, LOG_ERROR,
- "Cannot open model file '%s'\n",
- in_name);
- res = RES_IO_ERR;
+ settings = MEM_CALLOC(green->allocator, green->nthreads, sizeof(*settings));
+ if(settings == NULL) {
+ res = RES_MEM_ERR;
goto error;
}
- txtrdr_stream(green->allocator, stream, in_name, '#', &txtrdr);
- for(;;) {
- char* line;
- ERR(txtrdr_read_line(txtrdr));
- line = txtrdr_get_line(txtrdr);
- if(!line) break;
- if(mode & MODE_EXTENTED_RESULTS) str_set(&keep, line);
+
+ omp_set_num_threads((int)green->nthreads);
+ #pragma omp parallel for schedule(static)
+ for(i = 0; i < (int64_t)sz; i++) {
+ char* line = darray_char_data_get(darray_line_data_get(&green->settings) + i);
+ struct result* result = darray_result_data_get(&green->results) + i;
+ res_T tmp_res = RES_OK;
+ int t = omp_get_thread_num();
+
+ if(res != RES_OK) continue;
+
+ if(settings[t] == NULL) {
+ /* desc_count + 1 for AMBIENT */
+ settings[t] = MEM_CALLOC(green->allocator, 1 + green->counts.desc_count,
+ sizeof(**settings));
+ if(settings[t] == NULL) {
+ res = RES_MEM_ERR;
+ continue;
+ }
+ }
+
/* Apply settings */
- ERR(parse_line(in_name, line, green));
+ applied_settings_set_defaults(green, settings[t]);
+ tmp_res = parse_line(in_name, line, green, settings[t]);
+ if(tmp_res != RES_OK) {
+ res = tmp_res;
+ logger_print(green->logger, LOG_ERROR,
+ "Cannot parse settings line: %s\n",
+ str_cget(&result->keep));
+ continue;
+ }
/* Compute */
- green_compute_1(green, &E, &STD);
- /* Print results */
- if(mode & MODE_EXTENTED_RESULTS)
- fprintf(out_stream, "%g +/- %g ; %s\n", E, STD, str_cget(&keep));
- else fprintf(out_stream, "%g %g\n", E, STD);
- }
- txtrdr_ref_put(txtrdr);
- txtrdr = NULL;
+ green_compute_1(green, settings[t], &result->E, &result->STD);
+ } /* Implicit barrier */
+ if(res != RES_OK) goto error;
exit:
- str_release(&keep);
- if(stream) fclose(stream);
- if(txtrdr) txtrdr_ref_put(txtrdr);
+ if(settings) {
+ FOR_EACH(i, 0, green->nthreads) MEM_RM(green->allocator, settings[i]);
+ MEM_RM(green->allocator, settings);
+ }
return res;
error:
goto exit;
diff --git a/src/green-compute.h b/src/green-compute.h
@@ -33,8 +33,6 @@ build_green_table
res_T
green_compute
(struct green* green,
- const char* in_name,
- const int mode,
- FILE* out_stream);
+ const char* in_name);
#endif /* GREEN_COMPUTE_H */
\ No newline at end of file
diff --git a/src/green-input.c b/src/green-input.c
@@ -20,6 +20,7 @@
#include <rsys/str.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
+#include <rsys/text_reader.h>
#include <stdlib.h>
@@ -53,7 +54,7 @@ error:
}
res_T
-read_green
+read_green_function
(struct green* green,
FILE* stream)
{
@@ -125,3 +126,89 @@ end:
error:
goto end;
}
+
+
+/* BEGIN HACK */
+
+#include <rsys/ref_count.h>
+struct txtrdr {
+ FILE* stream; /* Stream of the text to read */
+ struct str name; /* Stream name */
+ size_t nlines; /* # read lines */
+ struct darray_char line; /* Buffer storing the read line */
+
+ /* String of chars from which the remaining line chars are skipped */
+ char reject[4];
+
+ /* Boolean defining if the stream is internally managed or not, i.e. if it
+ * has to be closed on text_reader release or not */
+ int manage_stream;
+
+ struct mem_allocator* allocator;
+ ref_T ref;
+};
+
+static INLINE res_T
+txtrdr_copy_line_and_release
+ (struct txtrdr* txtrdr,
+ struct darray_char* line)
+{
+ res_T res = RES_OK;
+ ASSERT(txtrdr && line);
+ ERR(darray_char_copy_and_release(line, &txtrdr->line));
+ ERR(darray_char_resize(&txtrdr->line, 32));
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+
+/* END HACK */
+
+
+
+
+res_T
+green_read_settings
+ (struct green* green,
+ const char* in_name)
+{
+ res_T res = RES_OK;
+ struct txtrdr* txtrdr = NULL;
+ FILE* stream = NULL;
+
+ ASSERT(green && in_name);
+
+ stream = fopen(in_name, "r");
+ if (!stream) {
+ logger_print(green->logger, LOG_ERROR,
+ "Cannot open model file '%s'\n",
+ in_name);
+ res = RES_IO_ERR;
+ goto error;
+ }
+ txtrdr_stream(green->allocator, stream, in_name, '#', &txtrdr);
+ for (;;) {
+ char* line;
+ size_t sz;
+ ERR(txtrdr_read_line(txtrdr));
+ line = txtrdr_get_line(txtrdr);
+ if (!line) break;
+ sz = darray_line_size_get(&green->settings);
+ ERR(darray_line_resize(&green->settings, 1 + sz));
+ ERR(darray_result_resize(&green->results, 1 + sz));
+ ERR(txtrdr_copy_line_and_release(txtrdr,
+ darray_line_data_get(&green->settings) + sz));
+ str_set(&darray_result_data_get(&green->results)[sz].keep, line);
+ }
+ txtrdr_ref_put(txtrdr);
+ txtrdr = NULL;
+
+exit:
+ if (stream) fclose(stream);
+ if (txtrdr) txtrdr_ref_put(txtrdr);
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/green-main.c b/src/green-main.c
@@ -23,6 +23,7 @@
#include <rsys/logger.h>
#include <stdlib.h>
+#include <omp.h>
int
main
@@ -67,20 +68,33 @@ main
if(args.verbose < 3)
logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL);
- if(args.green_filename) {
- stream = fopen(args.green_filename, "rb");
- if(!stream) {
- logger_print(&logger, LOG_ERROR,
- "Cannot open model file '%s'\n", args.green_filename);
- res = RES_IO_ERR;
- goto error;
+ green_init(&allocator, &logger, args.nthreads, &green);
+ green_initialized = 1;
+ #pragma omp parallel sections num_threads(args.nthreads)
+ {
+ /* If there are some settings to apply read the 2 files at the same time*/
+ #pragma omp section
+ if(args.green_filename) {
+ stream = fopen(args.green_filename, "rb");
+ if(!stream) {
+ logger_print(&logger, LOG_ERROR,
+ "Cannot open model file '%s'\n", args.green_filename);
+ res = RES_IO_ERR;
+ } else {
+ res_T tmp_err;
+ tmp_err = read_green_function(&green, stream);
+ fclose(stream);
+ if(tmp_err != RES_OK) res = tmp_err;
+ }
}
- green_init(&allocator, &logger, &green);
- green_initialized = 1;
- ERR(read_green(&green, stream));
- fclose(stream); stream = NULL;
- }
-
+ #pragma omp section
+ if(args.mode & MODE_APPLY_GREEN) {
+ res_T tmp_res;
+ tmp_res = green_read_settings(&green, args.command_filename);
+ if(tmp_res != RES_OK) res = tmp_res;
+ }
+ } /* Implicit barrier */
+ if(res != RES_OK) goto error;
if(args.mode & MODE_HTML_SUMMARY) {
ASSERT(args.info_filename);
stream = fopen(args.info_filename, "w");
@@ -95,7 +109,8 @@ main
}
if(args.mode & MODE_APPLY_GREEN) {
- ERR(green_compute(&green, args.command_filename, args.mode, stdout));
+ ERR(green_compute(&green, args.command_filename));
+ green_print_result(&green, args.mode, stdout);
}
exit:
diff --git a/src/green-output.c b/src/green-output.c
@@ -98,6 +98,26 @@ short_help
}
void
+green_print_result
+ (struct green* green,
+ const int mode,
+ FILE* out_stream)
+{
+ size_t i, sz;
+
+ ASSERT(green && out_stream);
+ sz = darray_line_size_get(&green->settings);
+
+ for (i = 0; i < sz; i++) {
+ struct result* result = darray_result_data_get(&green->results) + i;
+ if (mode & MODE_EXTENTED_RESULTS)
+ fprintf(out_stream, "%g +/- %g ; %s\n", result->E, result->STD,
+ str_cget(&result->keep));
+ else fprintf(out_stream, "%g %g\n", result->E, result->STD);
+ }
+}
+
+void
dump_green_info
(struct green* green,
FILE* stream)
@@ -228,7 +248,8 @@ dump_green_info
k = (double)green->table[i].end_weight
/ (double)green->counts.ok_count;
t += k * green->table[i].end_value;
- fprintf(stream, "%g * <b>%s</b>", k, str_cget(&green->table[i].end_name));
+ fprintf(stream, "%g * <b>%s</b>",
+ k, str_cget(&green->table[i].end_name));
}
}
ASSERT(!fst);
@@ -239,7 +260,8 @@ dump_green_info
k = (double)green->table[i].other_weight
/ (double)green->counts.ok_count;
t += k * green->table[i].other_value;
- fprintf(stream, " + %g * <b>%s</b>", k, str_cget(&green->table[i].other_name));
+ fprintf(stream, " + %g * <b>%s</b>",
+ k, str_cget(&green->table[i].other_name));
}
}
if(green->table[green->counts.desc_count].end_weight) {
diff --git a/src/green-output.h b/src/green-output.h
@@ -32,6 +32,12 @@ short_help
FILE* stream);
void
+green_print_result
+ (struct green* green,
+ const int mode,
+ FILE* out_stream);
+
+void
dump_green_info
(struct green* green,
FILE* stream);
diff --git a/src/green-types.h b/src/green-types.h
@@ -19,8 +19,11 @@
#include <rsys/str.h>
#include <rsys/mem_allocator.h>
#include <rsys/hash_table.h>
+#include <rsys/dynamic_array.h>
+#include <rsys/dynamic_array_char.h>
#include <string.h>
+#include <omp.h>
/* Utility macros */
#define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0
@@ -176,9 +179,14 @@ release_sample
}
/*
- * Table used to compute green
+ * Types used to compute green
*/
+struct applied_settings_elt {
+ double end_value;
+ double other_value;
+};
+
struct table_elt {
struct str end_name, other_name;
double end_value, other_value;
@@ -215,7 +223,7 @@ release_table_elt
}
struct variable_data {
- double* value;
+ size_t idx;
int used;
int unknown;
};
@@ -231,6 +239,59 @@ struct variable_data {
#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
#include <rsys/hash_table.h>
+#define DARRAY_NAME line
+#define DARRAY_DATA struct darray_char
+#define DARRAY_FUNCTOR_INIT darray_char_init
+#define DARRAY_FUNCTOR_RELEASE darray_char_release
+#define DARRAY_FUNCTOR_COPY darray_char_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_char_copy_and_release
+#include <rsys/dynamic_array.h>
+
+struct result {
+ double E, STD;
+ struct str keep;
+};
+
+static FINLINE void
+result_init(struct mem_allocator* alloc, struct result* data)
+{
+ ASSERT(alloc && data);
+ str_init(alloc, &data->keep);
+}
+
+static FINLINE void
+result_release(struct result* data)
+{
+ ASSERT(data);
+ str_release(&data->keep);
+}
+
+static FINLINE res_T
+result_copy(struct result* dst, struct result const* src)
+{
+ ASSERT(dst && src);
+ dst->E = src->E;
+ dst->STD = src->STD;
+ return str_copy(&dst->keep, &src->keep);
+}
+
+static FINLINE res_T
+result_copy_and_release(struct result* dst, struct result* src)
+{
+ ASSERT(dst && src);
+ dst->E = src->E;
+ dst->STD = src->STD;
+ return str_copy_and_release(&dst->keep, &src->keep);
+}
+
+#define DARRAY_NAME result
+#define DARRAY_DATA struct result
+#define DARRAY_FUNCTOR_INIT result_init
+#define DARRAY_FUNCTOR_RELEASE result_release
+#define DARRAY_FUNCTOR_COPY result_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE result_copy_and_release
+#include <rsys/dynamic_array.h>
+
/*
* Main type to store binary file content
*/
@@ -244,13 +305,17 @@ struct green {
struct table_elt* table;
struct sample* samples;
int references_checked, unused_variables, unknown_variables;
+ unsigned nthreads;
struct htable_variable_ptr variable_ptrs;
+ struct darray_line settings;
+ struct darray_result results;
};
static INLINE void
green_init
(struct mem_allocator* alloc,
struct logger* logger,
+ const unsigned nthreads,
struct green* green)
{
ASSERT(alloc && green);
@@ -266,7 +331,10 @@ green_init
green->references_checked = 0;
green->unused_variables = 0;
green->unknown_variables = 0;
+ green->nthreads = MMIN(nthreads, (unsigned)omp_get_num_procs());
htable_variable_ptr_init(alloc, &green->variable_ptrs);
+ darray_line_init(alloc, &green->settings);
+ darray_result_init(alloc, &green->results);
}
static INLINE void
@@ -286,13 +354,21 @@ green_release
MEM_RM(green->allocator, green->samples);
green->allocator = NULL;
htable_variable_ptr_release(&green->variable_ptrs);
+ darray_line_release(&green->settings);
+ darray_result_release(&green->results);
}
res_T
-read_green
+read_green_function
(struct green* green,
FILE* stream);
+res_T
+green_read_settings
+ (struct green* green,
+ const char* in_name);
+
+
/*
* Different types of descriptions read from the binary file
*/