From c2b9dfdd2998a895134d153f341250bc9f9e1618 Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Mon, 11 Nov 2024 17:42:57 +0100 Subject: [PATCH] Memory management tweaks There are no memory leaks, yet, I discover, with my steady course, thru my small valgrind peeks, that nvidia are a bunch of stupid a-holes. --- include/cx.h | 4 +- include/cx_thread.h | 1 + include/neural.h | 1 + src/cx.c | 96 ++++++++++++++++++++++++++++++++------------- src/cx_thread.c | 23 +++++++++++ src/neural.c | 18 ++++++++- 6 files changed, 113 insertions(+), 30 deletions(-) diff --git a/include/cx.h b/include/cx.h index ca40dc8..c329911 100644 --- a/include/cx.h +++ b/include/cx.h @@ -32,6 +32,7 @@ typedef struct _cx_gl_ctx { GLFWwindow *window; ModelRegistry *mr; GLuint *VertexArrayIDs; + void (*free)(void *self); size_t VertexArray_count; size_t VertexArray_size; GLuint *programIDs; @@ -43,6 +44,7 @@ typedef struct _cx_nn_ctx { Neural_Network *nn; float *input_buffer; float *output_buffer; + void (*free)(void *self); } CX_NN_CTX; typedef struct _cx_ctx { @@ -55,7 +57,7 @@ typedef struct _cx_ctx { CX_Context *cx_context_new(void); -int cx_glinit(GLFWwindow **); +int cx_glinit(CX_GL_CTX **); int cx_nninit(Neural_Network **); int cx_init(CX_Context **); diff --git a/include/cx_thread.h b/include/cx_thread.h index f8775fb..4d513f4 100644 --- a/include/cx_thread.h +++ b/include/cx_thread.h @@ -14,6 +14,7 @@ typedef struct _cx_thrgr { } CX_ThreadGroup; CX_ThreadGroup *cx_threadGroup_new(void *(*)(void *), void *); +void cx_threadGroup_free(CX_ThreadGroup *); #endif diff --git a/include/neural.h b/include/neural.h index 5a6dff4..eaa7919 100644 --- a/include/neural.h +++ b/include/neural.h @@ -26,6 +26,7 @@ typedef struct _neural_data { } Neural_Data; Neural_Network *neural_new(size_t, size_t, size_t); +void neural_free(Neural_Network *); void neural_randomize(Neural_Network *); float *neural_process(Neural_Network *, float *); Neural_Data *neural_getData(Neural_Network *, size_t); diff --git a/src/cx.c b/src/cx.c index f688d1e..20a42e8 100644 --- a/src/cx.c +++ b/src/cx.c @@ -80,13 +80,58 @@ cx_loadShaders(GLuint *VertexArrayID, GLuint *programID) { return 0; } +void +gl_ctx_free(void *self) { + CX_GL_CTX *gl_ctx; + + gl_ctx = self; + + if (gl_ctx) { + free(gl_ctx->VertexArrayIDs); + free(gl_ctx->programIDs); + modelRegistry_free(gl_ctx->mr); + } + free(gl_ctx); +} + +void +nn_ctx_free(void *self) { + CX_NN_CTX *nn_ctx; + + nn_ctx = self; + + if (nn_ctx) { + free(nn_ctx->input_buffer); + free(nn_ctx->output_buffer); + neural_free(nn_ctx->nn); + } + free(nn_ctx); +} + int -cx_glinit(GLFWwindow **window) { +cx_glinit(CX_GL_CTX **gl_ctx) { + // Initialize OpenGL context + + (*gl_ctx)->VertexArrayIDs = calloc(1, sizeof(GLuint)); + if (!(*gl_ctx)->VertexArrayIDs) { + goto err; + } + (*gl_ctx)->VertexArray_count = 0; + (*gl_ctx)->VertexArray_size = 1; + (*gl_ctx)->programIDs = calloc(1, sizeof(GLuint)); + if (!(*gl_ctx)->programIDs) { + goto err; + } + (*gl_ctx)->ProgramID_count = 0; + (*gl_ctx)->ProgramID_size = 1; + + (*gl_ctx)->free = &gl_ctx_free; + // Initialise GLFW printf("Initializing OpenGL.\n"); if(!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); - return -1; + goto err; } glfwWindowHint(GLFW_SAMPLES, 4); @@ -98,30 +143,33 @@ cx_glinit(GLFWwindow **window) { glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Open a window and create its OpenGL context - *window = glfwCreateWindow(1280, 720, "C-X", NULL, NULL); - if (*window == NULL) { + (*gl_ctx)->window = glfwCreateWindow(1280, 720, "C-X", NULL, NULL); + if ((*gl_ctx)->window == NULL) { fprintf(stderr, "Failed to open GLFW window.\n"); glfwTerminate(); - return -1; + goto err; } printf("Window created.\n"); - glfwMakeContextCurrent(*window); + glfwMakeContextCurrent((*gl_ctx)->window); // Initialize GLEW if (glewInit() != GLEW_OK) { fprintf(stderr, "Failed to initialize GLEW\n"); glfwTerminate(); - return -1; + goto err; } // Ensure we can capture the escape key being pressed below - glfwSetInputMode(*window, GLFW_STICKY_KEYS, GL_TRUE); + glfwSetInputMode((*gl_ctx)->window, GLFW_STICKY_KEYS, GL_TRUE); // Dark grey background glClearColor(0.15f, 0.15f, 0.15f, 0.0f); return 0; + +err: + return -1; } int @@ -147,27 +195,11 @@ cx_init(CX_Context **cx_ctx) { printf("Initializing CX.\n"); - gl_ctx = calloc(1, sizeof(CX_GL_CTX)); - - gl_ctx->VertexArrayIDs = calloc(1, sizeof(GLuint)); - if (!gl_ctx->VertexArrayIDs) { - goto err; - } - gl_ctx->VertexArray_count = 0; - gl_ctx->VertexArray_size = 1; - gl_ctx->programIDs = calloc(1, sizeof(GLuint)); - if (!gl_ctx->programIDs) { - goto err; - } - gl_ctx->ProgramID_count = 0; - gl_ctx->ProgramID_size = 1; - - // Establish a model registry - gl_ctx->mr = modelRegistry_new(); - nn_ctx = calloc(1, sizeof(CX_NN_CTX)); + nn_ctx->free = &nn_ctx_free; *cx_ctx = calloc(1, sizeof(CX_Context)); + gl_ctx = calloc(1, sizeof(CX_GL_CTX)); (*cx_ctx)->gl_ctx = gl_ctx; (*cx_ctx)->nn_ctx = nn_ctx; @@ -228,7 +260,7 @@ cx_glthread(void *self) { CX_Thread *self_t = self; CX_GL_CTX *gl_ctx = self_t->ctx; - cx_glinit(&gl_ctx->window); + cx_glinit(&gl_ctx); if (cx_loadShaders(gl_ctx->VertexArrayIDs, gl_ctx->programIDs)) { return NULL; @@ -253,6 +285,9 @@ int cx_run(CX_Context *ctx) { CX_ThreadGroup *tg[2]; + // Establish a model registry + ctx->gl_ctx->mr = modelRegistry_new(); + tg[1] = cx_threadGroup_new(&cx_nnthread, ctx->nn_ctx); pthread_join(tg[1]->group_manager->thread, NULL); @@ -263,7 +298,12 @@ cx_run(CX_Context *ctx) { pthread_join(tg[0]->group_manager->thread, NULL); - modelRegistry_free(ctx->gl_ctx->mr); + + cx_threadGroup_free(tg[0]); + cx_threadGroup_free(tg[1]); + + free(ctx->threads); + free(ctx); return 0; } diff --git a/src/cx_thread.c b/src/cx_thread.c index b6ddb45..cb5c774 100644 --- a/src/cx_thread.c +++ b/src/cx_thread.c @@ -23,6 +23,20 @@ err: return NULL; } +void +cx_thread_free(CX_Thread *self) { + if (self) { + /* TODO */ + /* This is naive in its current form and will shatter + * sooner or later. + * Fix the context structures so that this call + * is guaranteed not to touch invalid memory. + */ + ((CX_GL_CTX *)self->ctx)->free(self->ctx); + } + free(self); +} + CX_ThreadGroup * cx_threadGroup_new(void *(*target)(void *), void *ctx) { @@ -39,3 +53,12 @@ cx_threadGroup_new(void *(*target)(void *), return self; } +void +cx_threadGroup_free(CX_ThreadGroup *self) { + if (self) { + cx_thread_free(self->group_manager); + free(self->workers); + } + free(self); +} + diff --git a/src/neural.c b/src/neural.c index 3d2984e..de35c05 100644 --- a/src/neural.c +++ b/src/neural.c @@ -17,7 +17,12 @@ nl_new(size_t layer_size, size_t layer_size_next) { static void nl_free(Neural_Layer *self) { - free(self->neurons); + if (self) { + for (int i = 0; i < self->layer_size; i++) { + free(self->neurons[i].synapses); + } + free(self->neurons); + } free(self); } @@ -51,6 +56,17 @@ neural_new(size_t input_size, size_t output_size, size_t layer_count) { return self; } +void +neural_free(Neural_Network *self) { + if (self) { + for (int i = 0; i < self->layer_count; i++) { + nl_free(self->layers[i]); + } + free(self->layers); + } + free(self); +} + void neural_randomize(Neural_Network *self) { FILE *f;