mirror of
https://github.com/TREX-CoE/Sherman-Morrison.git
synced 2024-12-25 05:43:54 +01:00
Merge pull request #52 from PurplePachyderm/dev
Update integration of vfc_probes
This commit is contained in:
commit
8b39bc44c2
@ -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_hl.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"
|
||||
CXXFLAGS = -O0 -g $(H5FLAGS)
|
||||
## MKL linker flags
|
||||
@ -20,11 +20,11 @@ ifeq ($(MKL),-DMKL)
|
||||
ifeq ($(ENV),INTEL)
|
||||
LFLAGS = -mkl=sequential # implicit
|
||||
else
|
||||
LFLAGS = $(H5LFLAGS) -lvfc_probes
|
||||
LFLAGS = $(H5LFLAGS)
|
||||
endif
|
||||
endif
|
||||
H5CXXFLAGS = $(CXXFLAGS)
|
||||
FFLAGS = $(CXXFLAGS)
|
||||
FFLAGS = $(CXXFLAGS) -lvfc_probes_f
|
||||
|
||||
INCLUDE = -I $(INC_DIR)/
|
||||
DEPS_CXX = $(OBJ_DIR)/SM_Maponi.o \
|
||||
|
@ -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));
|
||||
}
|
@ -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;
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
#include "Helpers.hpp"
|
||||
#include "SM_Maponi.hpp"
|
||||
#include "SM_Standard.hpp"
|
||||
#include "vfc_probe.h"
|
||||
#include <vfc_probes.h>
|
||||
|
||||
using namespace H5;
|
||||
// #define DEBUG
|
||||
@ -140,9 +140,9 @@ int test_cycle(H5File file, int cycle, std::string version,
|
||||
showMatrix(res, dim, "Result");
|
||||
#endif
|
||||
|
||||
vfc_put_probe(probes, &(zero_padded_group)[0], &("frob2_" + version)[0],
|
||||
vfc_probe(probes, &(zero_padded_group)[0], &("frob2_" + version)[0],
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user