multithreading work (need to make better)

This commit is contained in:
2026-05-26 18:04:12 +02:00
parent e2ffcb972b
commit d499b9bbaa
4 changed files with 126 additions and 21 deletions

View File

@@ -1,6 +1,7 @@
CC := gcc
CFLAGS := -Wall -Wextra -g -fsanitize=address,undefined $(shell sdl2-config --cflags)
CFLAGS += -O3 -march=native
CFLAGS += -O3 -march=native -fopt-info-optimized
#CFLAGS += -fsanitize=address
LDFLAGS := $(shell sdl2-config --libs)
TARGET := game_of_life

View File

@@ -1,4 +1,6 @@
#include "game_core.h"
#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
const int directions[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
@@ -73,3 +75,57 @@ Board process_game(Board board) {
board.pixels = tmp;
return board;
}
void* process_chunk(void* arg) {
ThreadArgs* ta = (ThreadArgs*)arg;
Board board = (*ta[0].board);
size_t x, y;
uint8_t count = 0;
for (y = ta->y_start; y < ta->y_end; y++) {
for (x = 0; x < board.width; x++) {
count = count_adjacent(board, x, y);
if (board.pixels[y * board.width + x] == BLACK && count == 3) {
board.next_pixels[y * board.width + x] = WHITE;
} else if (board.pixels[y * board.width + x] == WHITE &&
count != 2 && count != 3) {
board.next_pixels[y * board.width + x] = BLACK;
} else {
board.next_pixels[y * board.width + x] =
board.pixels[y * board.width + x];
}
}
}
return NULL;
}
ThreadArgs* make_chunk(Board* board, size_t n_threads) {
size_t i;
size_t chunk = board->height / n_threads;
ThreadArgs* output = malloc(sizeof(ThreadArgs) * n_threads);
for (i = 0; i < n_threads; i++) {
output[i].board = board;
output[i].y_start = i * chunk;
output[i].y_end =
(i == n_threads - 1) ? board->height : (i + 1) * chunk;
}
return output;
}
Board process_game_mt(ThreadArgs* ta,
Board board,
pthread_t* threads,
size_t n_threads) {
size_t i = 0;
for (i = 0; i < n_threads; i++) {
ta[i].board = &board;
pthread_create(&threads[i], NULL, process_chunk, &ta[i]);
}
for (i = 0; i < n_threads; i++) {
pthread_join(threads[i], NULL);
}
uint32_t* tmp = board.next_pixels;
board.next_pixels = board.pixels;
board.pixels = tmp;
return board;
}

View File

@@ -14,10 +14,22 @@ typedef struct {
size_t height;
} Board;
typedef struct {
Board* board;
size_t y_start;
size_t y_end;
} ThreadArgs;
void free_board(Board board);
Board init_board(size_t width, size_t height, int random);
int count_adjacent(Board board, size_t x, size_t y);
ThreadArgs* make_chunk(Board* board, size_t n_threads);
Board process_game(Board board);
Board process_game_mt(ThreadArgs* ta,
Board board,
pthread_t* threads,
size_t n_threads);
void display_board(Board board);
void* process_chunk(void* ta);
#endif

View File

@@ -1,17 +1,24 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_keycode.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_timer.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "game_core.h"
#include "utils.h"
#define SEED (5)
#define WIDTH (800)
#define HEIGHT (600)
#define SIM_WIDTH (800)
#define SIM_HEIGHT (600)
#define SIM_WIDTH (80)
#define SIM_HEIGHT (60)
const int FPS = 15;
const int FRAME_DELAY = 1000 / FPS;
t_flags process_args(int argc, char** argv) {
t_flags output_flags = {0};
@@ -36,54 +43,83 @@ t_flags process_args(int argc, char** argv) {
}
int main(int argc, char* argv[]) {
pthread_t* threads;
int n_threads = sysconf(_SC_NPROCESSORS_ONLN);
size_t n_chunk;
ThreadArgs* ta;
t_flags flags = process_args(argc, argv);
printf("G : %d , M : %d (n : %d)\n", flags.graphical, flags.multithread,
n_threads);
srand(time(NULL));
if (flags.graphical) {
Board b = init_board(SIM_WIDTH, SIM_HEIGHT, 0);
Board b = init_board(SIM_WIDTH, SIM_HEIGHT, 1);
b.pixels[0 * SIM_WIDTH + 1] = WHITE;
b.pixels[1 * SIM_WIDTH + 2] = WHITE;
b.pixels[2 * SIM_WIDTH + 0] = WHITE;
b.pixels[2 * SIM_WIDTH + 1] = WHITE;
b.pixels[2 * SIM_WIDTH + 2] = WHITE;
if (flags.multithread) {
ta = make_chunk(&b, (int)n_threads);
threads = malloc(sizeof(pthread_t) * n_threads);
n_chunk = b.height / n_threads;
}
// SDL2
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* win = SDL_CreateWindow("pixels", 0, 0, WIDTH, HEIGHT, 0);
SDL_Renderer* ren =
SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
SDL_Texture* tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
SIM_WIDTH, SIM_HEIGHT);
int running = 1;
SDL_Event e;
int pitch;
void* tex_pixels;
// While running frames
int running = 1;
int paused = 0;
int next_frame = 0;
Uint32 frame_start;
Uint32 frame_time;
SDL_Rect dst = {0, 0, WIDTH, HEIGHT};
while (running) {
while (SDL_PollEvent(&e))
frame_start = SDL_GetTicks();
if (next_frame)
next_frame = 0;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT)
running = 0;
if (e.type == SDL_KEYDOWN) {
if (e.key.keysym.sym == SDLK_SPACE)
paused = !paused;
if (e.key.keysym.sym == SDLK_RIGHT)
next_frame = 1;
}
}
SDL_Rect dst = {0, 0, WIDTH, HEIGHT};
if (!paused || next_frame) {
SDL_LockTexture(tex, NULL, &tex_pixels, &pitch);
memcpy(tex_pixels, b.pixels,
SIM_WIDTH * SIM_HEIGHT * sizeof(uint32_t));
SDL_UnlockTexture(tex);
// SDL_UpdateTexture(tex, NULL, b.pixels,SIM_WIDTH *
// sizeof(uint32_t));
// SDL_RenderClear(ren);
SDL_RenderCopy(ren, tex, NULL, &dst);
SDL_RenderPresent(ren);
b = process_game(b);
// SDL_Delay(100);
b = !flags.multithread
? process_game(b)
: process_game_mt(ta, b, threads, n_threads);
}
frame_time = SDL_GetTicks() - frame_start;
if (frame_time < FRAME_DELAY)
SDL_Delay(FRAME_DELAY - frame_time);
}
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
free_board(b);
free(threads);
} else {
Board b = init_board(SIM_WIDTH, SIM_HEIGHT, 1);