stardis-green

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

commit b47435992c6ef48df230168c9a3ff372eed71b03
parent 7624330c92d33ecf6bce87e0c5c7d1306b9bb407
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Mon, 26 Oct 2020 17:00:44 +0100

Improve warn/err reporting on settings

Diffstat:
Msrc/green-compute.c | 222+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 132 insertions(+), 90 deletions(-)

diff --git a/src/green-compute.c b/src/green-compute.c @@ -23,6 +23,7 @@ #include <rsys/logger.h> #include <rsys/text_reader.h> #include <rsys/dynamic_array.h> +#include <rsys/mem_allocator.h> #include <math.h> #include <string.h> @@ -39,43 +40,32 @@ enum log_record_type { struct log_record { enum log_record_type type; + int line_num, var_num; struct str name; const char* keep_line; double default_value; + struct mem_allocator* allocator; }; -static FINLINE void -log_record_init - (struct mem_allocator* allocator, - struct log_record* data) -{ - data->type = RECORD_TYPES_UNDEF__; - data->keep_line = NULL; - data->default_value = INF; - str_init(allocator, &data->name); -} - -static FINLINE res_T -log_record_copy - (struct log_record* dst, - struct log_record const* src) -{ - dst->type = src->type; - dst->keep_line = src->keep_line; - dst->default_value = src->default_value; - return str_copy(&dst->name, &src->name); -} - - static FINLINE res_T -log_record_copy_and_release - (struct log_record* dst, - struct log_record* src) +log_record_create + (struct mem_allocator* allocator, + const enum log_record_type type, + struct log_record** out_record) { - dst->type = src->type; - dst->keep_line = src->keep_line; - dst->default_value = src->default_value; - return str_copy_and_release(&dst->name, &src->name); + struct log_record* record; + ASSERT(allocator && out_record); + record = MEM_ALLOC(allocator, sizeof(*record)); + if(!record) return RES_MEM_ERR; + record->type = type; + record->line_num = UINT_MAX; + record->var_num = UINT_MAX; + record->keep_line = NULL; + record->default_value = INF; + str_init(allocator, &record->name); + record->allocator = allocator; + *out_record = record; + return RES_OK; } static FINLINE void @@ -83,14 +73,11 @@ log_record_release (struct log_record* data) { str_release(&data->name); + MEM_RM(data->allocator, data); } #define DARRAY_NAME logs -#define DARRAY_DATA struct log_record -#define DARRAY_FUNCTOR_INIT log_record_init -#define DARRAY_FUNCTOR_COPY log_record_copy -#define DARRAY_FUNCTOR_COPY_AND_RELEASE log_record_copy_and_release -#define DARRAY_FUNCTOR_RELEASE log_record_release +#define DARRAY_DATA struct log_record* #include <rsys/dynamic_array.h> void @@ -335,6 +322,18 @@ green_compute_1 *STD = (V > 0) ? sqrt(V / (double)green->counts.ok_count) : 0; } +static int +cmp_records + (void const* r1, void const* r2) +{ + ASSERT(r1 && r2); + const struct log_record* record1 = *(struct log_record**)r1; + const struct log_record* record2 = *(struct log_record**)r2; + if(record1->line_num == record2->line_num) + return record1->var_num - record2->var_num; + return record1->line_num - record2->line_num; +} + static void do_log (const char* file_name, @@ -342,13 +341,20 @@ do_log struct darray_logs* logs) { size_t i; + int prev_line_num = INT_MAX; enum log_type log_type = LOG_WARNING; ASSERT(file_name && green && logs); if(darray_logs_size_get(logs) == 0) return; + /* Sort records by #line */ + qsort(darray_logs_data_get(logs), + darray_logs_size_get(logs), + sizeof(*darray_logs_data_get(logs)), + cmp_records); + FOR_EACH(i, 0, darray_logs_size_get(logs)) { - struct log_record* record = darray_logs_data_get(logs) + i; + struct log_record* record = darray_logs_data_get(logs)[i]; if(record->type & (RECORD_INVALID | RECORD_UNKNOWN)) { log_type = LOG_ERROR; break; @@ -356,38 +362,71 @@ do_log } logger_print(green->logger, log_type, "In file '%s':\n", file_name); FOR_EACH(i, 0, darray_logs_size_get(logs)) { - struct log_record* record = darray_logs_data_get(logs) + i; + struct log_record* record = darray_logs_data_get(logs)[i]; switch (record->type) { case RECORD_INVALID: - logger_print(green->logger, LOG_ERROR, - "In line '%s':\n\tInvalid data (missing name)\n", - record->keep_line); + if(record->line_num != prev_line_num) { + logger_print(green->logger, LOG_ERROR, + "In line #%d: '%s':\n", + record->line_num, record->keep_line); + logger_print(green->logger, LOG_ERROR, + (str_is_empty(&record->name) + ? "Invalid data (missing name)\n" : "Invalid data (missing value)\n")); + } else + logger_print(green->logger, LOG_ERROR, + (str_is_empty(&record->name) + ? "Invalid data (missing name)\n" : "Invalid data (missing value)\n")); break; case RECORD_UNKNOWN: - logger_print(green->logger, LOG_ERROR, - "In line '%s':\n\tUnknown variable name: '%s'\n", - record->keep_line, str_cget(&record->name)); + if(record->line_num != prev_line_num) { + logger_print(green->logger, LOG_ERROR, + "In line #%d: '%s':\n", + record->line_num, record->keep_line); + logger_print(green->logger, LOG_ERROR, + "Unknown variable name: '%s'\n", + str_cget(&record->name)); + } else + logger_print(green->logger, LOG_ERROR, + "\tUnknown variable name: '%s'\n", + str_cget(&record->name)); break; case RECORD_UNUSED: - logger_print(green->logger, LOG_WARNING, - "In line '%s':\n\tAttempt to change unused variable '%s'.\n", - record->keep_line, str_cget(&record->name)); + if(record->line_num != prev_line_num) { + logger_print(green->logger, LOG_WARNING, + "In line #%d: '%s':\n", + record->line_num, record->keep_line); + logger_print(green->logger, LOG_WARNING, + "Attempt to change unused variable '%s'.\n", + str_cget(&record->name)); + } else + logger_print(green->logger, LOG_WARNING, + "\tAttempt to change unused variable '%s'.\n", + str_cget(&record->name)); break; case RECORD_DEFAULT: - logger_print(green->logger, LOG_WARNING, - "In line '%s':\n\tChange variable '%s' to its default value %g.\n", - record->keep_line, str_cget(&record->name), record->default_value); + if(record->line_num != prev_line_num) { + logger_print(green->logger, LOG_WARNING, + "In line #%d: '%s':\n", + record->line_num, record->keep_line); + logger_print(green->logger, LOG_WARNING, + "Change variable '%s' to its default value %g.\n", + str_cget(&record->name), record->default_value); + } else + logger_print(green->logger, LOG_WARNING, + "Change variable '%s' to its default value %g.\n", + str_cget(&record->name), record->default_value); break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } + prev_line_num = record->line_num; } } static res_T parse_line (const char* file_name, - const int64_t idx, + const int idx, struct green* green, struct applied_settings_elt* settings, struct darray_logs* logs) @@ -395,11 +434,12 @@ parse_line res_T res = RES_OK; int name_count; struct str name; - char* tk = NULL; + char* tk_name = NULL; + char* tk_value = NULL; char* tok_ctx = NULL; const struct str* keep_line; struct str line; - ASSERT(file_name && green); + ASSERT(file_name && green && settings && logs && idx >= 0); keep_line = darray_str_cdata_get(&green->settings) + idx; str_init(green->allocator, &line); @@ -410,66 +450,64 @@ parse_line /* At least one name=value, no name without value */ for(name_count = 0; ; name_count++) { struct variable_data* vd; - struct log_record record; + struct log_record* record = NULL; double prev; if(res != RES_OK) goto error; - record.keep_line = str_cget(keep_line); /* Just in case */ - - tk = strtok_r(name_count ? NULL : str_get(&line), "=", &tok_ctx); - if(tk) { + tk_name = strtok_r(name_count ? NULL : str_get(&line), "=", &tok_ctx); + if(tk_name) { char* c; - c = tk + strlen(tk) - 1; - while(c >= tk && isspace(*tk)) tk++; - while(c >= tk && isspace(*c)) { + c = tk_name + strlen(tk_name) - 1; + while(c >= tk_name && isspace(*tk_name)) tk_name++; + while(c >= tk_name && isspace(*c)) { *c = '\0'; c--; } - if(c < tk) tk = NULL; + if(c < tk_name) tk_name = NULL; } - if(!tk) { - if(name_count == 0) { - /* At least 1 name */ - record.type = RECORD_INVALID; - str_init(green->allocator, &record.name); - res = RES_BAD_ARG; - goto push_record; - } - else break; + tk_value = strtok_r(NULL, " \t", &tok_ctx); + if((tk_name == NULL) != (tk_value == NULL)) { + /* '<name> = <value>' or '' */ + ERR(log_record_create(green->allocator, RECORD_INVALID, &record)); + if(tk_name) ERR(str_set(&record->name, tk_name)); + res = RES_BAD_ARG; + goto push_record; } - ERR(str_set(&name, tk)); - CHK_TOK(strtok_r(NULL, " \t", &tok_ctx), "value"); + if(!tk_name) break; /* End of data */ + /* Check name validity */ + ERR(str_set(&name, tk_name)); vd = htable_variable_ptr_find(&green->variable_ptrs, &name); if(!vd) { - record.type = RECORD_UNKNOWN; - str_init(green->allocator, &record.name); - ERR(str_copy(&record.name, &name)); + ERR(log_record_create(green->allocator, RECORD_UNKNOWN, &record)); + ERR(str_set(&record->name, tk_name)); res = RES_BAD_ARG; goto push_record; } if(!vd->used) { - record.type = RECORD_UNUSED; - str_init(green->allocator, &record.name); - ERR(str_copy(&record.name, &name)); + ERR(log_record_create(green->allocator, RECORD_UNUSED, &record)); + ERR(str_set(&record->name, tk_name)); goto push_record; } /* Variable exists and is used in Green function: check if really changed */ prev = ((double*)settings)[vd->idx]; - ERR(cstr_to_double(tk, ((double*)settings) + vd->idx)); + ERR(cstr_to_double(tk_value, ((double*)settings) + vd->idx)); if(prev == ((double*)settings)[vd->idx]) { - record.type = RECORD_DEFAULT; - str_init(green->allocator, &record.name); - ERR(str_copy(&record.name, &name)); - record.default_value = prev; + ERR(log_record_create(green->allocator, RECORD_DEFAULT, &record)); + ERR(str_set(&record->name, tk_name)); + record->default_value = prev; goto push_record; } continue; push_record: #pragma omp critical { - res_T tmp_res = darray_logs_push_back(logs, &record); - str_release(&record.name); + res_T tmp_res; + ASSERT(record && record->type != RECORD_TYPES_UNDEF__); + record->line_num = idx; + record->var_num = name_count; + record->keep_line = str_cget(keep_line); + tmp_res = darray_logs_push_back(logs, &record); if(res == RES_OK) res = tmp_res; } } @@ -488,14 +526,14 @@ green_compute const char* in_name) { res_T res = RES_OK; - size_t sz; - int64_t i; + size_t sz, n; + int i; struct applied_settings_elt** settings = NULL; struct darray_logs logs; ASSERT(green && in_name); sz = darray_str_size_get(&green->settings); - ASSERT(sz < INT64_MAX); + ASSERT(sz < INT_MAX); settings = MEM_CALLOC(green->allocator, green->nthreads, sizeof(*settings)); if(settings == NULL) { @@ -506,7 +544,7 @@ green_compute omp_set_num_threads((int)green->nthreads); #pragma omp parallel for schedule(static) - for(i = 0; i < (int64_t)sz; i++) { + for(i = 0; i < (int)sz; i++) { struct result* result = darray_result_data_get(&green->results) + i; res_T tmp_res = RES_OK; int t = omp_get_thread_num(); @@ -538,9 +576,13 @@ green_compute exit: do_log(in_name, green, &logs); if(settings) { - FOR_EACH(i, 0, green->nthreads) MEM_RM(green->allocator, settings[i]); + FOR_EACH(n, 0, green->nthreads) MEM_RM(green->allocator, settings[n]); MEM_RM(green->allocator, settings); } + FOR_EACH(n, 0, darray_logs_size_get(&logs)) { + struct log_record* record = darray_logs_data_get(&logs)[n]; + log_record_release(record); + } darray_logs_release(&logs); return res; error: