tipe/test/cnn_matrix_multiplication.cu

149 lines
3.9 KiB
Plaintext
Raw Normal View History

2022-10-14 18:17:29 +02:00
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>
#include <omp.h>
2022-10-14 18:17:29 +02:00
2022-10-24 12:54:51 +02:00
#include "../src/cnn/include/matrix_multiplication.h"
2023-02-18 13:10:00 +01:00
#include "../src/include/memory_management.h"
#include "../src/include/colors.h"
#include "../src/include/utils.h"
2022-10-14 18:17:29 +02:00
float random_float(float low, float high) {
float t = (float)rand() / (float)RAND_MAX;
return (1.0f - t) * low + t * high;
}
void fill_matrix_random(float **matrix, int n, int p) {
for (int i=0; i < n; i++) {
for (int j=0; j < p; j++) {
matrix[i][j] = random_float(0.0f, 15.0f);
}
}
}
void print_matrix(float** mat, int n, int p) {
for (int i=0; i < n; i++) {
printf("[\t");
for (int j=0; j < p; j++) {
printf("%0.1f\t", mat[i][j]);
}
printf("]\n");
}
}
float** create_matrix(int n, int p) {
float** matrix = (float**)nalloc(n, sizeof(float*));
2022-10-14 18:17:29 +02:00
for (int i=0; i < n; i++) {
matrix[i] = (float*)nalloc(p, sizeof(float));
2022-10-14 18:17:29 +02:00
}
fill_matrix_random(matrix, n, p);
return matrix;
}
float** create_empty_matrix(int n, int p) {
float** matrix = (float**)nalloc(n, sizeof(float*));
2022-10-14 18:17:29 +02:00
for (int i=0; i < n; i++) {
matrix[i] = (float*)nalloc(p, sizeof(float));
2022-10-14 18:17:29 +02:00
for (int j=0; j < p; j++) {
matrix[i][j] = 0.;
}
}
return matrix;
}
2022-10-21 14:36:26 +02:00
bool check_matrices_equality(float** m1, float** m2, int n, int p, int acceptation) {
2022-10-14 18:17:29 +02:00
for (int i=0; i < n; i++) {
for (int j=0; j < p; j++) {
2022-10-21 14:36:26 +02:00
if (fabs(m1[i][j] - m2[i][j]) > 0.01*acceptation) {
return false;
2022-10-14 18:17:29 +02:00
}
}
}
return true;
}
2022-10-21 14:36:26 +02:00
void run_matrices_test(int n, int p, int q) {
double start_time, end_time;
2022-11-01 17:24:29 +01:00
double cpu_time_used, gpu_time_used;
2022-10-14 18:17:29 +02:00
float** matrix1 = create_matrix(n, p);
float** matrix2 = create_matrix(p, q);
float** result_gpu = create_empty_matrix(n, q);
float** result_cpu = create_empty_matrix(n, q);
printf("(%d,%d)x(%d,%d) Data generation complete.\n", n, p, p, q);
start_time = omp_get_wtime();
2022-10-14 18:17:29 +02:00
matrix_multiplication_device(matrix1, matrix2, result_gpu, n, p, q);
end_time = omp_get_wtime();
2022-10-14 18:17:29 +02:00
cpu_time_used = end_time - start_time;
2022-10-21 14:36:26 +02:00
printf("(%d,%d)x(%d,%d) Time used for GPU: %lf seconds\n", n, p, p, q, cpu_time_used);
2022-10-14 19:56:39 +02:00
start_time = omp_get_wtime();
2022-10-14 19:56:39 +02:00
matrix_multiplication_host(matrix1, matrix2, result_cpu, n, p, q);
end_time = omp_get_wtime();
2022-10-14 18:17:29 +02:00
gpu_time_used = end_time - start_time;
2022-11-01 17:24:29 +01:00
printf("(%d,%d)x(%d,%d) Time used for CPU: %lf seconds\n", n, p, p, q, gpu_time_used);
2022-10-14 18:17:29 +02:00
2022-10-21 14:36:26 +02:00
// Vérification de l'égalité des matrices
printf("(%d,%d)x(%d,%d) Checking equality.\n", n, p, p, q);
if (!check_matrices_equality(result_gpu, result_cpu, n, q, p)) {
exit(1);
}
printf(GREEN "OK\n" RESET);
2022-10-21 14:36:26 +02:00
// On libère l'espace mémoire alloué
for (int i=0; i < n; i++) {
2023-01-28 22:04:38 +01:00
gree(matrix1[i]);
2022-10-21 14:36:26 +02:00
}
2023-01-28 22:04:38 +01:00
gree(matrix1);
2022-10-21 14:36:26 +02:00
for (int i=0; i < p; i++) {
2023-01-28 22:04:38 +01:00
gree(matrix2[i]);
2022-10-21 14:36:26 +02:00
}
2023-01-28 22:04:38 +01:00
gree(matrix2);
2022-10-21 14:36:26 +02:00
for (int i=0; i < n; i++) {
2023-01-28 22:04:38 +01:00
gree(result_cpu[i]);
2022-10-21 14:36:26 +02:00
}
2023-01-28 22:04:38 +01:00
gree(result_cpu);
2022-10-14 18:17:29 +02:00
2022-10-21 14:36:26 +02:00
for (int i=0; i < n; i++) {
2023-01-28 22:04:38 +01:00
gree(result_gpu[i]);
2022-10-21 14:36:26 +02:00
}
2023-01-28 22:04:38 +01:00
gree(result_gpu);
2022-10-21 14:36:26 +02:00
}
int main() {
printf("Checking CUDA compatibility.\n");
bool cuda_compatible = check_cuda_compatibility();
if (!cuda_compatible) {
2022-11-11 11:41:21 +01:00
printf(RED "CUDA not compatible, skipping tests.\n" RESET);
2022-10-21 14:36:26 +02:00
return 0;
2022-10-14 18:17:29 +02:00
}
printf(GREEN "OK\n" RESET);
2022-10-21 14:36:26 +02:00
srand(time(NULL));
run_matrices_test(200, 1000, 200);
run_matrices_test(200, 1000, 20);
run_matrices_test(20, 1000, 200);
2022-10-14 18:17:29 +02:00
return 0;
2022-10-14 19:56:39 +02:00
}
// On obtient une différence entre le calcul fait par le GPU et par le CPU.
// Cette différence est linéaire en p. (err_moy = p*1.639e-6)
// Elle ne varie pas en fonction de n et q.
// Cette erreur est sûrement dûe à différences mineurs dans la précision du stockage des flottants
2022-10-21 14:36:26 +02:00
// dans la mémoire RAM et VRAM (du GPU)