Implement threading

This commit is contained in:
Marcel Plch 2024-11-10 21:28:17 +01:00
parent 3da9e7df5a
commit 0ea88cb6bc
Signed by: dormouse
GPG key ID: 2CA77596BC4BDFFE
5 changed files with 166 additions and 104 deletions

View file

@ -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

View file

@ -19,36 +19,36 @@
#include <GLFW/glfw3.h>
// Include project headers
#include <cx_thread.h>
#include <tensor.h>
#include <model.h>
#include <tensor.h>
#include <shader.h>
#include <neural.h>
#include <shader.h>
// 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

19
include/cx_thread.h Normal file
View file

@ -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

177
src/cx.c
View file

@ -1,41 +1,5 @@
#include <cx.h>
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;
}

41
src/cx_thread.c Normal file
View file

@ -0,0 +1,41 @@
#include <cx.h>
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;
}