Merge pull request #52 from PurplePachyderm/dev

Update integration of vfc_probes
This commit is contained in:
Aurélien Delval 2021-09-02 12:44:05 +02:00 committed by GitHub
commit 8b39bc44c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 6 additions and 471 deletions

View File

@ -10,7 +10,7 @@ H5FLAGS = "-I/usr/include/hdf5/serial \
/usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5_cpp.a \ /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5_cpp.a \
/usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5_hl.a \ /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5_hl.a \
/usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5.a \ /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5.a \
-lpthread -lsz -lz -ldl -lm \ -lpthread -lsz -lz -ldl -lm -lvfc_probes \
-Wl,-rpath -Wl,/usr/lib/x86_64-linux-gnu/hdf5/serial" -Wl,-rpath -Wl,/usr/lib/x86_64-linux-gnu/hdf5/serial"
CXXFLAGS = -O0 -g $(H5FLAGS) CXXFLAGS = -O0 -g $(H5FLAGS)
## MKL linker flags ## MKL linker flags
@ -20,11 +20,11 @@ ifeq ($(MKL),-DMKL)
ifeq ($(ENV),INTEL) ifeq ($(ENV),INTEL)
LFLAGS = -mkl=sequential # implicit LFLAGS = -mkl=sequential # implicit
else else
LFLAGS = $(H5LFLAGS) -lvfc_probes LFLAGS = $(H5LFLAGS)
endif endif
endif endif
H5CXXFLAGS = $(CXXFLAGS) H5CXXFLAGS = $(CXXFLAGS)
FFLAGS = $(CXXFLAGS) FFLAGS = $(CXXFLAGS) -lvfc_probes_f
INCLUDE = -I $(INC_DIR)/ INCLUDE = -I $(INC_DIR)/
DEPS_CXX = $(OBJ_DIR)/SM_Maponi.o \ DEPS_CXX = $(OBJ_DIR)/SM_Maponi.o \

View File

@ -1,248 +0,0 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2012 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#define HASH_MULTIPLIER 31
static const unsigned int hashmap_prime_1 = 73;
static const unsigned int hashmap_prime_2 = 5009;
#ifndef __VFC_HASHMAP_HEADER__
struct vfc_hashmap_st {
size_t nbits;
size_t mask;
size_t capacity;
size_t *items;
size_t nitems;
size_t n_deleted_items;
};
typedef struct vfc_hashmap_st *vfc_hashmap_t;
// allocate and initialize the map
vfc_hashmap_t vfc_hashmap_create();
// get the value at an index of a map
size_t get_value_at(size_t *items, size_t i);
// get the key at an index of a map
size_t get_key_at(size_t *items, size_t i);
// set the value at an index of a map
void set_value_at(size_t *items, size_t value, size_t i);
// set the key at an index of a map
void set_key_at(size_t *items, size_t key, size_t i);
// free the map
void vfc_hashmap_destroy(vfc_hashmap_t map);
// insert an element in the map
void vfc_hashmap_insert(vfc_hashmap_t map, size_t key, void *item);
// remove an element of the map
void vfc_hashmap_remove(vfc_hashmap_t map, size_t key);
// test if an element is in the map
char vfc_hashmap_have(vfc_hashmap_t map, size_t key);
// get an element of the map
void *vfc_hashmap_get(vfc_hashmap_t map, size_t key);
// get the number of elements in the map
size_t vfc_hashmap_num_items(vfc_hashmap_t map);
// Hash function
size_t vfc_hashmap_str_function(const char *id);
#endif
/***************** Verificarlo hashmap FUNCTIONS ********************
* The following set of functions are used in backends and wrapper
* to stock and access quickly internal data.
*******************************************************************/
// free the map
void vfc_hashmap_destroy(vfc_hashmap_t map) {
if (map) {
free(map->items);
}
free(map);
}
// allocate and initialize the map
vfc_hashmap_t vfc_hashmap_create() {
vfc_hashmap_t map = (vfc_hashmap_t)calloc(1, sizeof(struct vfc_hashmap_st));
if (map == NULL) {
return NULL;
}
map->nbits = 3;
map->capacity = (size_t)(1 << map->nbits);
map->mask = map->capacity - 1;
// an item is now a value and a key
map->items = (size_t *)calloc(map->capacity, 2 * sizeof(size_t));
if (map->items == NULL) {
vfc_hashmap_destroy(map);
return NULL;
}
map->nitems = 0;
map->n_deleted_items = 0;
return map;
}
size_t get_value_at(size_t *items, size_t i) { return items[i * 2]; }
size_t get_key_at(size_t *items, size_t i) { return items[(i * 2) + 1]; }
void set_value_at(size_t *items, size_t value, size_t i) {
items[i * 2] = value;
}
void set_key_at(size_t *items, size_t key, size_t i) {
items[(i * 2) + 1] = key;
}
// add a member in the table
static int hashmap_add_member(vfc_hashmap_t map, size_t key, void *item) {
size_t value = (size_t)item;
size_t ii;
if (value == 0 || value == 1) {
return -1;
}
ii = map->mask & (hashmap_prime_1 * key);
while (get_value_at(map->items, ii) != 0 &&
get_value_at(map->items, ii) != 1) {
if (get_value_at(map->items, ii) == value) {
return 0;
} else {
/* search free slot */
ii = map->mask & (ii + hashmap_prime_2);
}
}
map->nitems++;
if (get_value_at(map->items, ii) == 1) {
map->n_deleted_items--;
}
set_value_at(map->items, value, ii);
set_key_at(map->items, key, ii);
return 1;
}
// rehash the table if necessary
static void maybe_rehash_map(vfc_hashmap_t map) {
size_t *old_items;
size_t old_capacity, ii;
if (map->nitems + map->n_deleted_items >= (double)map->capacity * 0.85) {
old_items = map->items;
old_capacity = map->capacity;
map->nbits++;
map->capacity = (size_t)(1 << map->nbits);
map->mask = map->capacity - 1;
map->items = (size_t *)calloc(map->capacity, 2 * sizeof(size_t));
map->nitems = 0;
map->n_deleted_items = 0;
for (ii = 0; ii < old_capacity; ii++) {
hashmap_add_member(map, get_key_at(old_items, ii),
(void *)get_value_at(old_items, ii));
}
free(old_items);
}
}
// insert an element in the map
void vfc_hashmap_insert(vfc_hashmap_t map, size_t key, void *item) {
hashmap_add_member(map, key, item);
maybe_rehash_map(map);
}
// remove an element of the map
void vfc_hashmap_remove(vfc_hashmap_t map, size_t key) {
size_t ii = map->mask & (hashmap_prime_1 * key);
while (get_value_at(map->items, ii) != 0) {
if (get_key_at(map->items, ii) == key) {
set_value_at(map->items, 1, ii);
map->nitems--;
map->n_deleted_items++;
break;
} else {
ii = map->mask & (ii + hashmap_prime_2);
}
}
}
// test if an element is in the map
char vfc_hashmap_have(vfc_hashmap_t map, size_t key) {
size_t ii = map->mask & (hashmap_prime_1 * key);
while (get_value_at(map->items, ii) != 0) {
if (get_key_at(map->items, ii) == key) {
return 1;
} else {
ii = map->mask & (ii + hashmap_prime_2);
}
}
return 0;
}
// get an element of the map
void *vfc_hashmap_get(vfc_hashmap_t map, size_t key) {
size_t ii = map->mask & (hashmap_prime_1 * key);
while (get_value_at(map->items, ii) != 0) {
if (get_key_at(map->items, ii) == key) {
return (void *)get_value_at(map->items, ii);
} else {
ii = map->mask & (ii + hashmap_prime_2);
}
}
return NULL;
}
// get the number of elements in the map
size_t vfc_hashmap_num_items(vfc_hashmap_t map) { return map->nitems; }
// Hash function for strings
size_t vfc_hashmap_str_function(const char *id) {
unsigned const char *us;
us = (unsigned const char *)id;
size_t index = 0;
while (*us != '\0') {
index = index * HASH_MULTIPLIER + *us;
us++;
}
return index;
}
// Free the hashmap
void vfc_hashmap_free(vfc_hashmap_t map) {
for (int ii = 0; ii < map->capacity; ii++)
if (get_value_at(map->items, ii) != 0 && get_value_at(map->items, ii) != 0)
free((void *)get_value_at(map->items, ii));
}

View File

@ -1,217 +0,0 @@
/*
* This file defines "vfc_probes", a hashtable-based structure which can be used
* to place "probes" in a code and store the different values of test variables.
* These test results can then be exported in a CSV file, and used to generate a
* Verificarlo test report.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vfc_hashmap.h"
#define VAR_NAME(var) #var // Simply returns the name of var into a string
/*
* A probe containing a double value as well as its key, which is needed when
* dumping the probes
*/
struct vfc_probe_node {
char *key;
double value;
};
typedef struct vfc_probe_node vfc_probe_node;
/*
* The probes structure. It simply acts as a wrapper for a Verificarlo hashmap.
*/
struct vfc_probes {
vfc_hashmap_t map;
};
typedef struct vfc_probes vfc_probes;
/*
* Initialize an empty vfc_probes instance
*/
vfc_probes vfc_init_probes() {
vfc_probes probes;
probes.map = vfc_hashmap_create();
return probes;
}
/*
* Free all probes
*/
void vfc_free_probes(vfc_probes *probes) {
// Before freeing the map, iterate manually over all items to free the keys
vfc_probe_node *probe = NULL;
for (int i = 0; i < probes->map->capacity; i++) {
probe = (vfc_probe_node *)get_value_at(probes->map->items, i);
if (probe != NULL) {
if (probe->key != NULL) {
free(probe->key);
}
}
}
vfc_hashmap_free(probes->map);
}
/*
* Helper function to generate the key from test and variable name
*/
char *gen_probe_key(char *testName, char *varName) {
char *key = (char *)malloc(strlen(testName) + strlen(varName) + 2);
strcpy(key, testName);
strcat(key, ",");
strcat(key, varName);
return key;
}
/*
* Helper function to detect forbidden character ',' in the keys
*/
void validate_probe_key(char *str) {
unsigned int len = strlen(str);
for (unsigned int i = 0; i < len; i++) {
if (str[i] == ',') {
fprintf(stderr,
"Error [verificarlo]: One of your probes has a ',' in its test \
or variable name (\"%s\"), which is forbidden\n",
str);
exit(1);
}
}
}
/*
* Add a new probe. If an issue with the key is detected (forbidden characters
* or a duplicate key), an error will be thrown.
*/
int vfc_put_probe(vfc_probes *probes, char *testName, char *varName,
double val) {
if (probes == NULL) {
return 1;
}
// Make sure testName and varName don't contain any ',', which would
// interfere with the key/CSV encoding
validate_probe_key(testName);
validate_probe_key(varName);
// Get the key, which is : testName + "," + varName
char *key = gen_probe_key(testName, varName);
// Look for a duplicate key
vfc_probe_node *oldProbe = (vfc_probe_node *)vfc_hashmap_get(
probes->map, vfc_hashmap_str_function(key));
if (oldProbe != NULL) {
if (strcmp(key, oldProbe->key) == 0) {
fprintf(stderr,
"Error [verificarlo]: you have a duplicate error with one of \
your probes (\"%s\"). Please make sure to use different names.\n",
key);
exit(1);
}
}
// Insert the element in the hashmap
vfc_probe_node *newProbe = (vfc_probe_node *)malloc(sizeof(vfc_probe_node));
newProbe->key = key;
newProbe->value = val;
vfc_hashmap_insert(probes->map, vfc_hashmap_str_function(key), newProbe);
return 0;
}
/*
* Remove (free) an element from the hash table
*/
int vfc_remove_probe(vfc_probes *probes, char *testName, char *varName) {
if (probes == NULL) {
return 1;
}
// Get the key, which is : testName + "," + varName
char *key = gen_probe_key(testName, varName);
vfc_hashmap_remove(probes->map, vfc_hashmap_str_function(key));
return 0;
}
/*
* Return the number of probes stored in the hashmap
*/
unsigned int vfc_num_probes(vfc_probes *probes) {
return vfc_hashmap_num_items(probes->map);
}
/*
* Dump probes in a .csv file (the double values are converted to hex), then
* free it.
*/
int vfc_dump_probes(vfc_probes *probes) {
if (probes == NULL) {
return 1;
}
// Get export path from the VFC_PROBES_OUTPUT env variable
char *exportPath = getenv("VFC_PROBES_OUTPUT");
if (!exportPath) {
printf("Warning [verificarlo]: VFC_PROBES_OUTPUT is not set, probes will \
not be dumped\n");
vfc_free_probes(probes);
return 0;
}
FILE *fp = fopen(exportPath, "w");
if (fp == NULL) {
fprintf(stderr,
"Error [verificarlo]: impossible to open the CSV file to save your \
probes (\"%s\")\n",
exportPath);
exit(1);
}
// First line gives the column names
fprintf(fp, "test,variable,value\n");
// Iterate over all table elements
vfc_probe_node *probe = NULL;
for (int i = 0; i < probes->map->capacity; i++) {
probe = (vfc_probe_node *)get_value_at(probes->map->items, i);
if (probe != NULL) {
fprintf(fp, "%s,%a\n", probe->key, probe->value);
}
}
fclose(fp);
vfc_free_probes(probes);
return 0;
}

View File

@ -13,7 +13,7 @@
#include "Helpers.hpp" #include "Helpers.hpp"
#include "SM_Maponi.hpp" #include "SM_Maponi.hpp"
#include "SM_Standard.hpp" #include "SM_Standard.hpp"
#include "vfc_probe.h" #include <vfc_probes.h>
using namespace H5; using namespace H5;
// #define DEBUG // #define DEBUG
@ -140,9 +140,9 @@ int test_cycle(H5File file, int cycle, std::string version,
showMatrix(res, dim, "Result"); showMatrix(res, dim, "Result");
#endif #endif
vfc_put_probe(probes, &(zero_padded_group)[0], &("frob2_" + version)[0], vfc_probe(probes, &(zero_padded_group)[0], &("frob2_" + version)[0],
frob2); frob2);
vfc_put_probe(probes, &(zero_padded_group)[0], &("res2_" + version)[0], res2); vfc_probe(probes, &(zero_padded_group)[0], &("res2_" + version)[0], res2);
delete[] res, updates, u, col_update_index, slater_matrix, slater_inverse; delete[] res, updates, u, col_update_index, slater_matrix, slater_inverse;