stardis-green

Post-processing of green functions
git clone git://git.meso-star.fr/stardis-green.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 5++++-
Mdoc/sgreen.1.txt.in | 2+-
Msrc/green-args.c | 2+-
Msrc/green-args.h | 2--
Msrc/green-compute.c | 117++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/green-compute.h | 4+---
Msrc/green-input.c | 89++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/green-main.c | 43+++++++++++++++++++++++++++++--------------
Msrc/green-output.c | 26++++++++++++++++++++++++--
Msrc/green-output.h | 6++++++
Msrc/green-types.h | 82++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
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 */