From 0ea88cb6bc829a3e7ef2dc683ff7f4fe864b70ec Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Sun, 10 Nov 2024 21:28:17 +0100 Subject: [PATCH] Implement threading --- CMakeLists.txt | 1 + include/cx.h | 32 ++++---- include/cx_thread.h | 19 +++++ src/cx.c | 177 ++++++++++++++++++++++---------------------- src/cx_thread.c | 41 ++++++++++ 5 files changed, 166 insertions(+), 104 deletions(-) create mode 100644 include/cx_thread.h create mode 100644 src/cx_thread.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b4d0730..9df851f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ add_executable( cx src/main.c src/cx.c + src/cx_thread.c src/tensor.c src/model.c src/shader.c diff --git a/include/cx.h b/include/cx.h index ed2f954..ca40dc8 100644 --- a/include/cx.h +++ b/include/cx.h @@ -19,36 +19,36 @@ #include // Include project headers +#include #include #include #include -#include #include +#include // Declare common data structures. -typedef struct _cx_thrd { - pthread_t thread; - void *ctx; // Arbitrary thread context -} CX_Thread; - -typedef struct _cx_thrgr { - CX_Thread *group_manager; - CX_Thread **workers; - size_t worker_count; - size_t worker_size; -} CX_ThreadGroup; - -typedef struct _cx_ctx { +typedef struct _cx_gl_ctx { GLFWwindow *window; - Neural_Network *nn; - CX_ThreadGroup **threads; + ModelRegistry *mr; GLuint *VertexArrayIDs; size_t VertexArray_count; size_t VertexArray_size; GLuint *programIDs; size_t ProgramID_count; size_t ProgramID_size; +} CX_GL_CTX; + +typedef struct _cx_nn_ctx { + Neural_Network *nn; + float *input_buffer; + float *output_buffer; +} CX_NN_CTX; + +typedef struct _cx_ctx { + CX_ThreadGroup **threads; + CX_GL_CTX *gl_ctx; + CX_NN_CTX *nn_ctx; } CX_Context; // Declare functions diff --git a/include/cx_thread.h b/include/cx_thread.h new file mode 100644 index 0000000..f8775fb --- /dev/null +++ b/include/cx_thread.h @@ -0,0 +1,19 @@ +#ifndef CX_THREAD_H +#define CX_THREAD_H + +typedef struct _cx_thrd { + pthread_t thread; + void *ctx; // Arbitrary thread context +} CX_Thread; + +typedef struct _cx_thrgr { + CX_Thread *group_manager; + CX_Thread **workers; + size_t worker_count; + size_t worker_size; +} CX_ThreadGroup; + +CX_ThreadGroup *cx_threadGroup_new(void *(*)(void *), void *); + +#endif + diff --git a/src/cx.c b/src/cx.c index e013925..2ffc45e 100644 --- a/src/cx.c +++ b/src/cx.c @@ -1,41 +1,5 @@ #include -static CX_Thread * -cx_thread_new(void *(*target)(void *), - void *ctx) { - CX_Thread *self; - int err; - - self = malloc(sizeof(CX_Thread)); - if (!self) { - goto err; - } - err = pthread_create(&self->thread, NULL, target, ctx); - if (err) { - goto err; - } - self->ctx = ctx; - -err: - free(self); - return NULL; -} - -static CX_ThreadGroup * -cx_threadGroup_new(void *(*target)(void *), - void *ctx) { - CX_ThreadGroup *self; - - self = malloc(sizeof(CX_ThreadGroup)); - - self->group_manager = cx_thread_new(target, ctx); - self->workers = malloc(8 * sizeof(CX_Thread *)); - self->worker_count = 0; - self->worker_size = 8; - - return self; -} - static void cx_glBindBuffer(GLfloat *render_buffer, GLuint buffer_address, GLuint gl_index, GLint member_size, GLsizeiptr bufsize) { @@ -140,6 +104,7 @@ cx_glinit(GLFWwindow **window) { glfwTerminate(); return -1; } + printf("Window created.\n"); glfwMakeContextCurrent(*window); @@ -175,46 +140,54 @@ cx_nninit(Neural_Network **nn) { return 0; } -static void -master_thread(void *ctx) { -} - int cx_init(CX_Context **cx_ctx) { - printf("Initializing CX."); + CX_GL_CTX *gl_ctx; + CX_NN_CTX *nn_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)); *cx_ctx = calloc(1, sizeof(CX_Context)); - (*cx_ctx)->VertexArrayIDs = calloc(1, sizeof(GLuint)); - if (!(*cx_ctx)->VertexArrayIDs) { - goto err; - } - (*cx_ctx)->VertexArray_count = 0; - (*cx_ctx)->VertexArray_size = 1; - (*cx_ctx)->programIDs = calloc(1, sizeof(GLuint)); - if (!(*cx_ctx)->programIDs) { - goto err; - } - (*cx_ctx)->ProgramID_count = 0; - (*cx_ctx)->ProgramID_size = 1; - (*cx_ctx)->threads = calloc(1, sizeof(CX_ThreadGroup)); + + (*cx_ctx)->gl_ctx = gl_ctx; + (*cx_ctx)->nn_ctx = nn_ctx; + + (*cx_ctx)->threads = calloc(1, sizeof(CX_ThreadGroup *)); if (!(*cx_ctx)->threads) { goto err; } - if (cx_glinit(&(*cx_ctx)->window)) { - goto err; - } - if (cx_nninit(&(*cx_ctx)->nn)) { - goto err; - } + + return 0; err: - if (*cx_ctx) { - free((*cx_ctx)->VertexArrayIDs); - free((*cx_ctx)->programIDs); + if ((*cx_ctx)->gl_ctx) { + free((*cx_ctx)->gl_ctx->VertexArrayIDs); + free((*cx_ctx)->gl_ctx->programIDs); free((*cx_ctx)->threads); } @@ -224,50 +197,78 @@ err: } static int -cx_glrun() { +cx_glrun(CX_GL_CTX *ctx) { + // Remainder from cursor experiments, might be useful later + double xpos, ypos; + glfwGetCursorPos(ctx->window, &xpos, &ypos); + + do { + cx_glrender(ctx->window, ctx->programIDs[0], ctx->mr); + usleep(1000000/60); + // Check if the ESC key was pressed or the window was closed + } while(glfwGetKey(ctx->window, GLFW_KEY_ESCAPE) != GLFW_PRESS + && !glfwWindowShouldClose(ctx->window)); + + // Close OpenGL window and terminate GLFW + glfwTerminate(); return 0; } static int -cx_nnrun(Neural_Network *nn) { +cx_nnrun(CX_Thread *self) { // Establish a neural interface. - float *input_buffer = malloc(64*sizeof(float)); float *output_buffer; + CX_NN_CTX *ctx = self->ctx; - output_buffer = neural_process(nn, input_buffer); + output_buffer = neural_process(ctx->nn, ctx->input_buffer); + + ctx->output_buffer = output_buffer; return 0; } +static void * +cx_glthread(void *self) { + CX_Thread *self_t = self; + CX_GL_CTX *gl_ctx = self_t->ctx; + + cx_glinit(&gl_ctx->window); + + if (cx_loadShaders(gl_ctx->VertexArrayIDs, gl_ctx->programIDs)) { + return NULL; + } + + cx_glrun(gl_ctx); + + return NULL; +} + +static void * +cx_nnthread(void *self) { + CX_Thread *self_t = self; + CX_NN_CTX *nn_ctx = self_t->ctx; + + cx_nninit(&nn_ctx->nn); + + return NULL; +} + int -cx_run(CX_Context *cx_ctx) { - ModelRegistry *mr; +cx_run(CX_Context *ctx) { + CX_ThreadGroup *tg[2]; - if (cx_loadShaders(cx_ctx->VertexArrayIDs, cx_ctx->programIDs)) { - return -1; - } + tg[1] = cx_threadGroup_new(&cx_nnthread, ctx->nn_ctx); - // Establish a model registry - mr = modelRegistry_new(); - // Fill the model registry with mesh models - neural_getMesh(cx_ctx->nn, mr); + pthread_join(tg[1]->group_manager->thread, NULL); - // Remainder from cursor experiments, might be useful later - double xpos, ypos; - glfwGetCursorPos(cx_ctx->window, &xpos, &ypos); + neural_getMesh(ctx->nn_ctx->nn, ctx->gl_ctx->mr); + tg[0] = cx_threadGroup_new(&cx_glthread, ctx->gl_ctx); - do { - cx_glrender(cx_ctx->window, cx_ctx->programIDs[0], mr); - usleep(1000000/60); - // Check if the ESC key was pressed or the window was closed - } while(glfwGetKey(cx_ctx->window, GLFW_KEY_ESCAPE) != GLFW_PRESS - && !glfwWindowShouldClose(cx_ctx->window)); + pthread_join(tg[0]->group_manager->thread, NULL); - // Close OpenGL window and terminate GLFW - glfwTerminate(); - modelRegistry_free(mr); + modelRegistry_free(ctx->gl_ctx->mr); return 0; } diff --git a/src/cx_thread.c b/src/cx_thread.c new file mode 100644 index 0000000..b6ddb45 --- /dev/null +++ b/src/cx_thread.c @@ -0,0 +1,41 @@ +#include + +CX_Thread * +cx_thread_new(void *(*target)(void *), + void *ctx) { + CX_Thread *self; + int err; + + self = malloc(sizeof(CX_Thread)); + if (!self) { + goto err; + } + self->ctx = ctx; + err = pthread_create(&self->thread, NULL, target, self); + if (err) { + goto err; + } + + return self; + +err: + free(self); + return NULL; +} + +CX_ThreadGroup * +cx_threadGroup_new(void *(*target)(void *), + void *ctx) { + CX_ThreadGroup *self; + + self = malloc(sizeof(CX_ThreadGroup)); + + self->workers = malloc(8 * sizeof(CX_Thread *)); + self->worker_count = 0; + self->worker_size = 8; + + self->group_manager = cx_thread_new(target, ctx); + + return self; +} +