diff --git a/Makefile b/Makefile index 79a8140..30713bb 100644 --- a/Makefile +++ b/Makefile @@ -25,8 +25,8 @@ TESTS_SRC_CU += $(wildcard test/*.cu) TESTS_OBJ = $(TESTS_SRC:test/%.c=$(BUILDDIR)/test-%) $(TESTS_SRC_CU:test/%.cu=$(BUILDDIR)/test-%) # Compile flags -CFLAGS = -std=gnu99 -lm -lpthread -ljpeg -NVCCFLAGS = -ljpeg +CFLAGS = -std=gnu99 -lm -lpthread -ljpeg -fopenmp +NVCCFLAGS = -ljpeg -Xcompiler -fopenmp # Additional warning rules CFLAGS += -Wall -Wextra @@ -35,6 +35,8 @@ NVCCFLAGS += # -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable # Compile with debug # -g +# See memory leaks and Incorrect Read/Write +# -fsanitize=address -lasan all: mnist cnn; # diff --git a/doc/cnn/neuron_io.md b/doc/cnn/neuron_io.md index fa1b0c8..256e826 100644 --- a/doc/cnn/neuron_io.md +++ b/doc/cnn/neuron_io.md @@ -34,6 +34,7 @@ On stocke pour chaque couche des informations supplémentaires en fonction de so type | nom de la variable | commentaire :---:|:---:|:---: uint32_t|activation| +uint32_t|linearisation| uint32_t|k_size| uint32_t|rows| uint32_t|columns| @@ -42,17 +43,19 @@ uint32_t|columns| type | nom de la variable | commentaire :---:|:---:|:---: uint32_t|activation| +uint32_t|linearisation| uint32_t|input_units| uint32_t|output_units| #### Si la couche est de type pooling: type | nom de la variable | commentaire :---:|:---:|:---: +uint32_t|linearisation| uint32_t|pooling| ### Corps -On constitue ensuite le corps du fichier à partir des données contenues dans chauqe couche de la manière suivante: +On constitue ensuite le corps du fichier à partir des données contenues dans chaque couche de la manière suivante: - Si la couche est de type pooling, on ne rajoute rien. diff --git a/src/cnn/include/initialisation.h b/src/cnn/include/initialisation.h index 7eb3c3c..80f6467 100644 --- a/src/cnn/include/initialisation.h +++ b/src/cnn/include/initialisation.h @@ -1,7 +1,7 @@ #ifndef DEF_INITIALISATION_H #define DEF_INITIALISATION_H -// Génère un flotant entre 0 et 1 +// Génère un flottant entre 0 et 1 #define RAND_FLT() ((float)rand())/((float)RAND_MAX) #define ZERO 0 diff --git a/src/cnn/jpeg.c b/src/cnn/jpeg.c index fb522a2..dd03f62 100644 --- a/src/cnn/jpeg.c +++ b/src/cnn/jpeg.c @@ -203,9 +203,7 @@ void free_dataset(jpegDataset* dataset) { } free(dataset->fileNames); free(dataset->labels); - #ifdef STORE_IMAGES_TO_RAM free(dataset->images); - #endif free(dataset); } diff --git a/src/cnn/make.c b/src/cnn/make.c index b403d3c..9f1016e 100644 --- a/src/cnn/make.c +++ b/src/cnn/make.c @@ -8,18 +8,18 @@ void make_average_pooling(float*** input, float*** output, int size, int output_depth, int output_dim) { // input[output_depth][output_dim+size-1][output_dim+size-1] // output[output_depth][output_dim][output_dim] - float average; + float sum; int n = size*size; for (int i=0; i < output_depth; i++) { for (int j=0; j < output_dim; j++) { for (int k=0; k < output_dim; k++) { - average = 0.; + sum = 0.; for (int a=0; a < size; a++) { for (int b=0; b < size; b++) { - average += input[i][size*j +a][size*k +b]; + sum += input[i][size*j +a][size*k +b]; } } - output[i][j][k] = average/(float)n; + output[i][j][k] = sum/(float)n; } } } diff --git a/src/cnn/neuron_io.c b/src/cnn/neuron_io.c index b25865b..32fe7f8 100644 --- a/src/cnn/neuron_io.c +++ b/src/cnn/neuron_io.c @@ -62,11 +62,12 @@ void write_couche(Network* network, int indice_couche, int type_couche, FILE* pt int output_dim = network->width[indice_couche+1]; // Écriture du pré-corps - uint32_t pre_buffer[4]; + uint32_t pre_buffer[5]; pre_buffer[0] = kernel->activation; - pre_buffer[1] = cnn->k_size; - pre_buffer[2] = cnn->rows; - pre_buffer[3] = cnn->columns; + pre_buffer[1] = kernel->linearisation; + pre_buffer[2] = cnn->k_size; + pre_buffer[3] = cnn->rows; + pre_buffer[4] = cnn->columns; fwrite(pre_buffer, sizeof(pre_buffer), 1, ptr); // Écriture du corps @@ -93,10 +94,11 @@ void write_couche(Network* network, int indice_couche, int type_couche, FILE* pt Kernel_nn* nn = kernel->nn; // Écriture du pré-corps - uint32_t pre_buffer[3]; + uint32_t pre_buffer[4]; pre_buffer[0] = kernel->activation; - pre_buffer[1] = nn->input_units; - pre_buffer[2] = nn->output_units; + pre_buffer[1] = kernel->linearisation; + pre_buffer[2] = nn->input_units; + pre_buffer[3] = nn->output_units; fwrite(pre_buffer, sizeof(pre_buffer), 1, ptr); // Écriture du corps @@ -111,8 +113,9 @@ void write_couche(Network* network, int indice_couche, int type_couche, FILE* pt } fwrite(buffer, sizeof(buffer), 1, ptr); } else if (type_couche == 2) { // Cas du Pooling Layer - uint32_t pre_buffer[1]; + uint32_t pre_buffer[2]; pre_buffer[0] = kernel->activation; // Variable du pooling + pre_buffer[1] = kernel->linearisation; fwrite(pre_buffer, sizeof(pre_buffer), 1, ptr); } } @@ -167,9 +170,10 @@ Network* read_network(char* filename) { // Lecture de chaque couche network->kernel = (Kernel**)malloc(sizeof(Kernel*)*size); - for (int i=0; i < (int)size; i++) { + for (int i=0; i < (int)size-1; i++) { network->kernel[i] = read_kernel(type_couche[i], network->width[i+1], ptr); } + network->kernel[(int)size-1] = read_kernel(type_couche[(int)size-1], -1, ptr); network->input = (float****)malloc(sizeof(float***)*size); for (int i=0; i < (int)size; i++) { // input[size][couche->depth][couche->dim][couche->dim] @@ -209,14 +213,14 @@ Kernel* read_kernel(int type_couche, int output_dim, FILE* ptr) { // Lecture du "Pré-corps" kernel->cnn = (Kernel_cnn*)malloc(sizeof(Kernel_cnn)); kernel->nn = NULL; - uint32_t buffer[4]; + uint32_t buffer[5]; fread(&buffer, sizeof(buffer), 1, ptr); kernel->activation = buffer[0]; - kernel->linearisation = 0; - kernel->cnn->k_size = buffer[1]; - kernel->cnn->rows = buffer[2]; - kernel->cnn->columns = buffer[3]; + kernel->linearisation = buffer[1]; + kernel->cnn->k_size = buffer[2]; + kernel->cnn->rows = buffer[3]; + kernel->cnn->columns = buffer[4]; // Lecture du corps Kernel_cnn* cnn = kernel->cnn; @@ -261,12 +265,13 @@ Kernel* read_kernel(int type_couche, int output_dim, FILE* ptr) { // Lecture du "Pré-corps" kernel->nn = (Kernel_nn*)malloc(sizeof(Kernel_nn)); kernel->cnn = NULL; - uint32_t buffer[3]; + uint32_t buffer[4]; fread(&buffer, sizeof(buffer), 1, ptr); kernel->activation = buffer[0]; - kernel->nn->input_units = buffer[1]; - kernel->nn->output_units = buffer[2]; + kernel->linearisation = buffer[1]; + kernel->nn->input_units = buffer[2]; + kernel->nn->output_units = buffer[3]; // Lecture du corps Kernel_nn* nn = kernel->nn; @@ -292,13 +297,14 @@ Kernel* read_kernel(int type_couche, int output_dim, FILE* ptr) { } } } else if (type_couche == 2) { // Cas du Pooling Layer - uint32_t pooling; + uint32_t pooling, linearisation; fread(&pooling, sizeof(pooling), 1, ptr); + fread(&linearisation, sizeof(linearisation), 1, ptr); kernel->cnn = NULL; kernel->nn = NULL; kernel->activation = pooling; - kernel->linearisation = pooling; // TODO: mettre à 0 la variable inutile + kernel->linearisation = linearisation; } return kernel; } \ No newline at end of file diff --git a/src/cnn/train.c b/src/cnn/train.c index 3e3dd80..7ac13b1 100644 --- a/src/cnn/train.c +++ b/src/cnn/train.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "../mnist/include/mnist.h" #include "include/initialisation.h" @@ -92,6 +93,13 @@ void train(int dataset_type, char* images_file, char* labels_file, char* data_di jpegDataset* dataset; // Structure de données décrivant un dataset d'images jpeg int* shuffle_index; // shuffle_index[i] contient le nouvel index de l'élément à l'emplacement i avant mélange + double start_time, end_time; + double elapsed_time; + + double algo_start = omp_get_wtime(); + + start_time = omp_get_wtime(); + if (dataset_type == 0) { // Type MNIST // Chargement des images du set de données MNIST int* parameters = read_mnist_images_parameters(images_file); @@ -113,7 +121,7 @@ void train(int dataset_type, char* images_file, char* labels_file, char* data_di // Initialisation du réseau if (!recover) { - network = create_network_lenet5(1, 0, TANH, GLOROT, input_dim, input_depth); + network = create_network_lenet5(0.1, 0, TANH, GLOROT, input_dim, input_depth); } else { network = read_network(recover); } @@ -179,8 +187,14 @@ void train(int dataset_type, char* images_file, char* labels_file, char* data_di train_params->nb_images = BATCHES; train_params->index = shuffle_index; #endif + end_time = omp_get_wtime(); + + elapsed_time = end_time - start_time; + printf("Initialisation: %0.2lf s\n\n", elapsed_time); for (int i=0; i < epochs; i++) { + + start_time = omp_get_wtime(); // La variable accuracy permet d'avoir une ESTIMATION // du taux de réussite et de l'entraînement du réseau, // mais n'est en aucun cas une valeur réelle dans le cas @@ -191,79 +205,110 @@ void train(int dataset_type, char* images_file, char* labels_file, char* data_di batches_epoques = div_up(nb_images_total, BATCHES); nb_images_total_remaining = nb_images_total; #ifndef USE_MULTITHREADING - train_params->nb_images = BATCHES; + train_params->nb_images = BATCHES; #endif for (int j=0; j < batches_epoques; j++) { #ifdef USE_MULTITHREADING - if (j == batches_epoques-1) { - nb_remaining_images = nb_images_total_remaining; - nb_images_total_remaining = 0; - } else { - nb_images_total_remaining -= BATCHES; - nb_remaining_images = BATCHES; - } - - for (int k=0; k < nb_threads; k++) { - if (k == nb_threads-1) { - train_parameters[k]->nb_images = nb_remaining_images; - nb_remaining_images = 0; + if (j == batches_epoques-1) { + nb_remaining_images = nb_images_total_remaining; + nb_images_total_remaining = 0; } else { - nb_remaining_images -= BATCHES / nb_threads; + nb_images_total_remaining -= BATCHES; + nb_remaining_images = BATCHES; } - train_parameters[k]->start = BATCHES*j + (BATCHES/nb_threads)*k; - train_parameters[k]->network = copy_network(network); - pthread_create( &tid[k], NULL, train_thread, (void*) train_parameters[k]); - } - for (int k=0; k < nb_threads; k++) { - // On attend la terminaison de chaque thread un à un - pthread_join( tid[k], NULL ); - accuracy += train_parameters[k]->accuracy / (float) nb_images_total; - } - - // On attend que tous les fils aient fini avant d'appliquer des modifications au réseau principal - for (int k=0; k < nb_threads; k++) { - update_weights(network, train_parameters[k]->network, train_parameters[k]->nb_images); - update_bias(network, train_parameters[k]->network, train_parameters[k]->nb_images); - free_network(train_parameters[k]->network); - } - current_accuracy = accuracy * nb_images_total/((j+1)*BATCHES); - printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "YELLOW"%0.1f%%"RESET" ", nb_threads, i, epochs, BATCHES*(j+1), nb_images_total, current_accuracy*100); - fflush(stdout); + for (int k=0; k < nb_threads; k++) { + if (k == nb_threads-1) { + train_parameters[k]->nb_images = nb_remaining_images; + nb_remaining_images = 0; + } else { + nb_remaining_images -= BATCHES / nb_threads; + } + train_parameters[k]->start = BATCHES*j + (BATCHES/nb_threads)*k; + + if (train_parameters[k]->start+train_parameters[k]->nb_images >= nb_images_total) { + train_parameters[k]->nb_images = nb_images_total - train_parameters[k]->start -1; + } + if (train_parameters[k]->nb_images > 0) { + train_parameters[k]->network = copy_network(network); + pthread_create( &tid[k], NULL, train_thread, (void*) train_parameters[k]); + } else { + train_parameters[k]->network = NULL; + } + } + for (int k=0; k < nb_threads; k++) { + // On attend la terminaison de chaque thread un à un + if (train_parameters[k]->network) { + pthread_join( tid[k], NULL ); + accuracy += train_parameters[k]->accuracy / (float) nb_images_total; + } + } + + // On attend que tous les fils aient fini avant d'appliquer des modifications au réseau principal + for (int k=0; k < nb_threads; k++) { + if (train_parameters[k]->network) { // Si le fil a été utilisé + update_weights(network, train_parameters[k]->network, train_parameters[k]->nb_images); + update_bias(network, train_parameters[k]->network, train_parameters[k]->nb_images); + free_network(train_parameters[k]->network); + } + } + current_accuracy = accuracy * nb_images_total/((j+1)*BATCHES); + printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "YELLOW"%0.2f%%"RESET" ", nb_threads, i, epochs, BATCHES*(j+1), nb_images_total, current_accuracy*100); + fflush(stdout); #else - (void)nb_images_total_remaining; // Juste pour enlever un warning + (void)nb_images_total_remaining; // Juste pour enlever un warning - train_params->start = j*BATCHES; + train_params->start = j*BATCHES; - // Ne pas dépasser le nombre d'images à cause de la partie entière - if (j == batches_epoques-1) { - train_params->nb_images = nb_images_total - j*BATCHES; - } - - train_thread((void*)train_params); - - accuracy += train_params->accuracy / (float) nb_images_total; - current_accuracy = accuracy * nb_images_total/((j+1)*BATCHES); - - update_weights(network, network, train_params->nb_images); - update_bias(network, network, train_params->nb_images); - - printf("\rÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "YELLOW"%0.1f%%"RESET" ", i, epochs, BATCHES*(j+1), nb_images_total, current_accuracy*100); - fflush(stdout); + // Ne pas dépasser le nombre d'images à cause de la partie entière + if (j == batches_epoques-1) { + train_params->nb_images = nb_images_total - j*BATCHES; + } + + train_thread((void*)train_params); + + accuracy += train_params->accuracy / (float) nb_images_total; + current_accuracy = accuracy * nb_images_total/((j+1)*BATCHES); + + update_weights(network, network, train_params->nb_images); + update_bias(network, network, train_params->nb_images); + + printf("\rÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "YELLOW"%0.4f%%"RESET" ", i, epochs, BATCHES*(j+1), nb_images_total, current_accuracy*100); + fflush(stdout); #endif } + end_time = omp_get_wtime(); + elapsed_time = end_time - start_time; #ifdef USE_MULTITHREADING - printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "GREEN"%0.1f%%"RESET" \n", nb_threads, i, epochs, nb_images_total, nb_images_total, accuracy*100); + printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "GREEN"%0.4f%%"RESET"\tTemps: %0.2f s\n", nb_threads, i, epochs, nb_images_total, nb_images_total, accuracy*100, elapsed_time); #else - printf("\rÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "GREEN"%0.1f%%"RESET" \n", i, epochs, nb_images_total, nb_images_total, accuracy*100); + printf("\rÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "GREEN"%0.4f%%"RESET"\tTemps: %0.2f s\n", i, epochs, nb_images_total, nb_images_total, accuracy*100, elapsed_time); #endif write_network(out, network); } free(shuffle_index); free_network(network); + #ifdef USE_MULTITHREADING free(tid); #else free(train_params); #endif + + if (dataset_type == 0) { + for (int i=0; i < nb_images_total; i++) { + for (int j=0; j < 28; j++) { + free(images[i][j]); + } + free(images[i]); + } + free(images); + free(labels); + } else { + free_dataset(dataset); + } + + end_time = omp_get_wtime(); + elapsed_time = end_time - algo_start; + printf("\nTemps total: %0.1f s\n", elapsed_time); } diff --git a/src/cnn/utils.c b/src/cnn/utils.c index c8aaed9..d9397f9 100644 --- a/src/cnn/utils.c +++ b/src/cnn/utils.c @@ -46,9 +46,10 @@ bool equals_networks(Network* network1, Network* network2) { printf(BOLDRED "[ ERROR ]" RESET "network1->kernel[%d] et network1->kernel[%d] diffèrent de type\n", i, i); return false; } + checkEquals(kernel[i]->linearisation, "kernel[i]->linearisation", i); if (!network1->kernel[i]->cnn && !network1->kernel[i]->nn) { // Type Pooling - // checkEquals(kernel[i]->linearisation, "kernel[i]->linearisation", i); + checkEquals(kernel[i]->activation, "kernel[i]->activation pour un pooling", i); } else if (!network1->kernel[i]->cnn) { // Type NN checkEquals(kernel[i]->nn->input_units, "kernel[i]->nn->input_units", i); diff --git a/src/mnist/main.c b/src/mnist/main.c index 6b8dccf..beb2642 100644 --- a/src/mnist/main.c +++ b/src/mnist/main.c @@ -8,6 +8,7 @@ #include "include/main.h" #include "include/mnist.h" +#include "../include/colors.h" #include "include/neuron_io.h" #include "include/neural_network.h" @@ -140,6 +141,7 @@ void train(int epochs, int layers, int neurons, char* recovery, char* image_file int repartition[3] = {neurons, 42, nb_neurons_last_layer}; float accuracy; + float current_accuracy; int nb_threads = get_nprocs(); pthread_t *tid = (pthread_t *)malloc(nb_threads * sizeof(pthread_t)); @@ -229,10 +231,11 @@ void train(int epochs, int layers, int neurons, char* recovery, char* image_file patch_network(network, train_parameters[j]->network, train_parameters[j]->nb_images); deletion_of_network(train_parameters[j]->network); } - printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: %0.1f%%", nb_threads, i, epochs, BATCHES*(k+1), nb_images_total, accuracy*100); + current_accuracy = accuracy*(nb_images_total/(BATCHES*(k+1))); + printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "YELLOW"%0.1f%%"RESET, nb_threads, i, epochs, BATCHES*(k+1), nb_images_total, current_accuracy*100); fflush(stdout); } - printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: %0.1f%%\n", nb_threads, i, epochs, nb_images_total, nb_images_total, accuracy*100); + printf("\rThreads [%d]\tÉpoque [%d/%d]\tImage [%d/%d]\tAccuracy: "GREEN"%0.1f%%"RESET"\n", nb_threads, i, epochs, nb_images_total, nb_images_total, accuracy*100); write_network(out, network); if (delta != NULL) write_delta_network(delta, delta_network); @@ -245,6 +248,16 @@ void train(int epochs, int layers, int neurons, char* recovery, char* image_file for (int j=0; j < nb_threads; j++) { free(train_parameters[j]); } + + for (int i=0; i < nb_images_total; i++) { + for (int j=0; j < height; j++) { + free(images[i][j]); + } + free(images[i]); + } + free(images); + free(labels); + free(shuffle_indices); free(train_parameters); // On libère les espaces mémoire utilisés spécialement sur le CPU diff --git a/src/mnist/neural_network.c b/src/mnist/neural_network.c index 6e40ccd..b5b070e 100644 --- a/src/mnist/neural_network.c +++ b/src/mnist/neural_network.c @@ -84,14 +84,15 @@ void deletion_of_network(Network* network) { for (int i=0; i < network->nb_layers; i++) { layer = network->layers[i]; - if (i != network->nb_layers-1) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants - for (int j=0; j < network->layers[i]->nb_neurons; j++) { - neuron = layer->neurons[j]; + + for (int j=0; j < network->layers[i]->nb_neurons; j++) { + neuron = layer->neurons[j]; + if (i != network->nb_layers-1) { // On exclut la dernière couche dont les neurones ne contiennent pas de poids sortants free(neuron->weights); free(neuron->back_weights); free(neuron->last_back_weights); - free(neuron); } + free(neuron); } free(layer->neurons); free(network->layers[i]); diff --git a/src/mnist/neuron_io.c b/src/mnist/neuron_io.c index e49758a..1d90031 100644 --- a/src/mnist/neuron_io.c +++ b/src/mnist/neuron_io.c @@ -24,15 +24,17 @@ Neuron* read_neuron(uint32_t nb_weights, FILE *ptr) { neuron->last_back_bias = 0.0; neuron->back_bias = 0.0; - neuron->last_back_weights = (float*)malloc(sizeof(float)*nb_weights); - neuron->back_weights = (float*)malloc(sizeof(float)*nb_weights); - neuron->weights = (float*)malloc(sizeof(float)*nb_weights); + if (nb_weights != 0) { + neuron->last_back_weights = (float*)malloc(sizeof(float)*nb_weights); + neuron->back_weights = (float*)malloc(sizeof(float)*nb_weights); + neuron->weights = (float*)malloc(sizeof(float)*nb_weights); - for (int i=0; i < (int)nb_weights; i++) { - fread(&tmp, sizeof(float), 1, ptr); - neuron->weights[i] = tmp; - neuron->back_weights[i] = 0.0; - neuron->last_back_weights[i] = 0.0; + for (int i=0; i < (int)nb_weights; i++) { + fread(&tmp, sizeof(float), 1, ptr); + neuron->weights[i] = tmp; + neuron->back_weights[i] = 0.0; + neuron->last_back_weights[i] = 0.0; + } } return neuron; diff --git a/src/mnist/utils.c b/src/mnist/utils.c index a5cf8e9..2477679 100644 --- a/src/mnist/utils.c +++ b/src/mnist/utils.c @@ -63,9 +63,7 @@ void print_weights(char* filename) { void count_labels(char* filename) { uint32_t number_of_images = read_mnist_labels_nb_images(filename); - - unsigned int* labels = (unsigned int*)malloc(sizeof(unsigned int)*number_of_images); - labels = read_mnist_labels(filename); + unsigned int* labels = read_mnist_labels(filename); unsigned int tab[10]; @@ -103,13 +101,15 @@ void create_network(char* filename, int sortie) { neuron->back_bias = 0.; neuron->last_back_bias = 0.; - neuron->weights = (float*)malloc(sizeof(float)*neurons_per_layer[i+1]); - neuron->back_weights = (float*)malloc(sizeof(float)*neurons_per_layer[i+1]); - neuron->last_back_weights = (float*)malloc(sizeof(float)*neurons_per_layer[i+1]); - for (int k=0; k < neurons_per_layer[i+1]; k++) { - neuron->weights[k] = 0.; - neuron->back_weights[k] = 0.; - neuron->last_back_weights[k] = 0.; + if (i != network->nb_layers-1) { + neuron->weights = (float*)malloc(sizeof(float)*neurons_per_layer[i+1]); + neuron->back_weights = (float*)malloc(sizeof(float)*neurons_per_layer[i+1]); + neuron->last_back_weights = (float*)malloc(sizeof(float)*neurons_per_layer[i+1]); + for (int k=0; k < neurons_per_layer[i+1]; k++) { + neuron->weights[k] = 0.; + neuron->back_weights[k] = 0.; + neuron->last_back_weights[k] = 0.; + } } layer->neurons[j] = neuron; } diff --git a/test/cnn_convolution.cu b/test/cnn_convolution.cu index d290adc..4e4779d 100644 --- a/test/cnn_convolution.cu +++ b/test/cnn_convolution.cu @@ -4,6 +4,7 @@ #include #include #include +#include #include "../src/cnn/include/convolution.h" #include "../src/cnn/include/struct.h" @@ -122,22 +123,23 @@ void run_convolution_test(int input_dim, int output_dim, int rows, int columns) // Lancement des calculs - clock_t start, end; + double start_time, end_time; double cpu_time_used, gpu_time_used; - start = clock(); + start_time = omp_get_wtime(); make_convolution_device(kernel, input, output_gpu, output_dim); - end = clock(); + end_time = omp_get_wtime(); - gpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; + + gpu_time_used = end_time - start_time; printf("(%d, %d, %d, %d) Time used for GPU: %lf seconds\n", rows, columns, input_dim, output_dim, gpu_time_used); - start = clock(); + start_time = omp_get_wtime(); make_convolution_cpu(kernel, input, output_cpu, output_dim); - end = clock(); + end_time = omp_get_wtime(); - cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; + cpu_time_used = end_time - start_time; printf("(%d, %d, %d, %d) Time used for CPU: %lf seconds\n", rows, columns, input_dim, output_dim, cpu_time_used); // Vérification de l'égalité des matrices diff --git a/test/cnn_matrix_multiplication.cu b/test/cnn_matrix_multiplication.cu index 2b8825c..69f1ce7 100644 --- a/test/cnn_matrix_multiplication.cu +++ b/test/cnn_matrix_multiplication.cu @@ -3,6 +3,7 @@ #include #include #include +#include #include "../src/cnn/include/matrix_multiplication.h" #include "../src/include/colors.h" @@ -70,7 +71,7 @@ bool check_matrices_equality(float** m1, float** m2, int n, int p, int acceptati } void run_matrices_test(int n, int p, int q) { - clock_t start, end; + double start_time, end_time; double cpu_time_used, gpu_time_used; float** matrix1 = create_matrix(n, p); @@ -79,18 +80,18 @@ void run_matrices_test(int n, int p, int q) { float** result_cpu = create_empty_matrix(n, q); printf("(%d,%d)x(%d,%d) Data generation complete.\n", n, p, p, q); - start = clock(); + start_time = omp_get_wtime(); matrix_multiplication_device(matrix1, matrix2, result_gpu, n, p, q); - end = clock(); + end_time = omp_get_wtime(); - cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; + cpu_time_used = end_time - start_time; printf("(%d,%d)x(%d,%d) Time used for GPU: %lf seconds\n", n, p, p, q, cpu_time_used); - start = clock(); + start_time = omp_get_wtime(); matrix_multiplication_host(matrix1, matrix2, result_cpu, n, p, q); - end = clock(); + end_time = omp_get_wtime(); - gpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; + gpu_time_used = end_time - start_time; printf("(%d,%d)x(%d,%d) Time used for CPU: %lf seconds\n", n, p, p, q, gpu_time_used); // Vérification de l'égalité des matrices diff --git a/test/cnn_neuron_io.c b/test/cnn_neuron_io.c index 8c54e9a..aa6e9d1 100644 --- a/test/cnn_neuron_io.c +++ b/test/cnn_neuron_io.c @@ -22,11 +22,16 @@ int main() { printf("Vérification de l'accès en lecture\n"); Network* network2 = read_network((char*)".test-cache/cnn_neuron_io.bin"); + Network* network3 = read_network((char*)".test-cache/cnn_neuron_io.bin"); printf(GREEN "OK\n" RESET); printf("Vérification de l'égalité des réseaux\n"); if (! equals_networks(network, network2)) { - printf_error(RED "Les deux réseaux obtenus ne sont pas égaux.\n" RESET); + printf_error(RED "Le réseau lu ne contient pas les mêmes données.\n" RESET); + exit(1); + } + if (! equals_networks(network2, network3)) { + printf_error(RED "La lecture du réseau donne des résultats différents.\n" RESET); exit(1); } printf(GREEN "OK\n" RESET); @@ -34,6 +39,7 @@ int main() { printf("Libération de la mémoire\n"); free_network(network); free_network(network2); + free_network(network3); printf(GREEN "OK\n" RESET); return 0; diff --git a/test/cnn_structure.c b/test/cnn_structure.c index eb47d05..5584377 100644 --- a/test/cnn_structure.c +++ b/test/cnn_structure.c @@ -21,7 +21,6 @@ int main() { kernel = network->kernel[i]; if ((!kernel->cnn)&&(!kernel->nn)) { printf("\n==== Couche %d de type "YELLOW"Pooling"RESET" ====\n", i); - printf("Linéarisation: %d\n", kernel->linearisation); } else if (!kernel->cnn) { printf("\n==== Couche %d de type "GREEN"NN"RESET" ====\n", i); printf("input: %d\n", kernel->nn->input_units); @@ -32,8 +31,12 @@ int main() { printf("rows: %d\n", kernel->cnn->rows); printf("columns: %d\n", kernel->cnn->columns); } + if (kernel->linearisation) { + printf(YELLOW"Linéarisation: %d\n"RESET, kernel->linearisation); + } printf("width: %d\n", network->width[i]); printf("depth: %d\n", network->depth[i]); + printf("activation: %d\n", kernel->activation); } printf(GREEN "\nOK\n" RESET); diff --git a/test/mnist_data_io.c b/test/mnist_data_io.c index b74ccb1..ae2aef5 100644 --- a/test/mnist_data_io.c +++ b/test/mnist_data_io.c @@ -49,5 +49,14 @@ int main() { read_test(nb_images, width, height, images, labels); printf(GREEN "OK\n" RESET); + for (int i=0; i < nb_images; i++) { + for (int j=0; j < height; j++) { + free(images[i][j]); + } + free(images[i]); + } + free(images); + free(labels); + free(parameters); return 0; } \ No newline at end of file diff --git a/test/mnist_neuron_io.c b/test/mnist_neuron_io.c index fee7dfe..6763e30 100644 --- a/test/mnist_neuron_io.c +++ b/test/mnist_neuron_io.c @@ -11,19 +11,21 @@ Neuron* creer_neuron(int nb_sortants) { Neuron* neuron = (Neuron*)malloc(sizeof(Neuron)); - neuron->weights = (float*)malloc(sizeof(float)*nb_sortants); - neuron->back_weights = (float*)malloc(sizeof(float)*nb_sortants); - neuron->last_back_weights = (float*)malloc(sizeof(float)*nb_sortants); + if (nb_sortants != 0) { + neuron->weights = (float*)malloc(sizeof(float)*nb_sortants); + neuron->back_weights = (float*)malloc(sizeof(float)*nb_sortants); + neuron->last_back_weights = (float*)malloc(sizeof(float)*nb_sortants); - for (int i=0; i < nb_sortants; i++) { - neuron->weights[i] = 0.5; - neuron->back_weights[i] = 0.0; - neuron->last_back_weights[i] = 0.0; + for (int i=0; i < nb_sortants; i++) { + neuron->weights[i] = 0.5; + neuron->back_weights[i] = 0.0; + neuron->last_back_weights[i] = 0.0; + } + neuron->z = 0.0; + neuron->bias = 0.0; + neuron->back_bias = 0.0; + neuron->last_back_bias = 0.0; } - neuron->z = 0.0; - neuron->bias = 0.0; - neuron->back_bias = 0.0; - neuron->last_back_bias = 0.0; return neuron; }