multithreading work (need to make better)
This commit is contained in:
3
Makefile
3
Makefile
@@ -1,6 +1,7 @@
|
|||||||
CC := gcc
|
CC := gcc
|
||||||
CFLAGS := -Wall -Wextra -g -fsanitize=address,undefined $(shell sdl2-config --cflags)
|
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)
|
LDFLAGS := $(shell sdl2-config --libs)
|
||||||
TARGET := game_of_life
|
TARGET := game_of_life
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "game_core.h"
|
#include "game_core.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
const int directions[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
|
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;
|
board.pixels = tmp;
|
||||||
return board;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,10 +14,22 @@ typedef struct {
|
|||||||
size_t height;
|
size_t height;
|
||||||
} Board;
|
} Board;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Board* board;
|
||||||
|
size_t y_start;
|
||||||
|
size_t y_end;
|
||||||
|
} ThreadArgs;
|
||||||
|
|
||||||
void free_board(Board board);
|
void free_board(Board board);
|
||||||
Board init_board(size_t width, size_t height, int random);
|
Board init_board(size_t width, size_t height, int random);
|
||||||
int count_adjacent(Board board, size_t x, size_t y);
|
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(Board board);
|
||||||
|
Board process_game_mt(ThreadArgs* ta,
|
||||||
|
Board board,
|
||||||
|
pthread_t* threads,
|
||||||
|
size_t n_threads);
|
||||||
void display_board(Board board);
|
void display_board(Board board);
|
||||||
|
void* process_chunk(void* ta);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
76
src/main.c
76
src/main.c
@@ -1,17 +1,24 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_keycode.h>
|
||||||
#include <SDL2/SDL_render.h>
|
#include <SDL2/SDL_render.h>
|
||||||
|
#include <SDL2/SDL_timer.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "game_core.h"
|
#include "game_core.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define SEED (5)
|
#define SEED (5)
|
||||||
#define WIDTH (800)
|
#define WIDTH (800)
|
||||||
#define HEIGHT (600)
|
#define HEIGHT (600)
|
||||||
#define SIM_WIDTH (800)
|
#define SIM_WIDTH (80)
|
||||||
#define SIM_HEIGHT (600)
|
#define SIM_HEIGHT (60)
|
||||||
|
|
||||||
|
const int FPS = 15;
|
||||||
|
const int FRAME_DELAY = 1000 / FPS;
|
||||||
|
|
||||||
t_flags process_args(int argc, char** argv) {
|
t_flags process_args(int argc, char** argv) {
|
||||||
t_flags output_flags = {0};
|
t_flags output_flags = {0};
|
||||||
@@ -36,54 +43,83 @@ t_flags process_args(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(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);
|
t_flags flags = process_args(argc, argv);
|
||||||
|
printf("G : %d , M : %d (n : %d)\n", flags.graphical, flags.multithread,
|
||||||
|
n_threads);
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
if (flags.graphical) {
|
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[0 * SIM_WIDTH + 1] = WHITE;
|
||||||
b.pixels[1 * SIM_WIDTH + 2] = WHITE;
|
b.pixels[1 * SIM_WIDTH + 2] = WHITE;
|
||||||
b.pixels[2 * SIM_WIDTH + 0] = WHITE;
|
b.pixels[2 * SIM_WIDTH + 0] = WHITE;
|
||||||
b.pixels[2 * SIM_WIDTH + 1] = WHITE;
|
b.pixels[2 * SIM_WIDTH + 1] = WHITE;
|
||||||
b.pixels[2 * SIM_WIDTH + 2] = 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_Init(SDL_INIT_VIDEO);
|
||||||
|
|
||||||
SDL_Window* win = SDL_CreateWindow("pixels", 0, 0, WIDTH, HEIGHT, 0);
|
SDL_Window* win = SDL_CreateWindow("pixels", 0, 0, WIDTH, HEIGHT, 0);
|
||||||
SDL_Renderer* ren =
|
SDL_Renderer* ren =
|
||||||
SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
|
SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
|
||||||
|
|
||||||
SDL_Texture* tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888,
|
SDL_Texture* tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888,
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
SIM_WIDTH, SIM_HEIGHT);
|
SIM_WIDTH, SIM_HEIGHT);
|
||||||
|
|
||||||
int running = 1;
|
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
int pitch;
|
int pitch;
|
||||||
void* tex_pixels;
|
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 (running) {
|
||||||
while (SDL_PollEvent(&e))
|
frame_start = SDL_GetTicks();
|
||||||
|
if (next_frame)
|
||||||
|
next_frame = 0;
|
||||||
|
while (SDL_PollEvent(&e)) {
|
||||||
if (e.type == SDL_QUIT)
|
if (e.type == SDL_QUIT)
|
||||||
running = 0;
|
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);
|
SDL_LockTexture(tex, NULL, &tex_pixels, &pitch);
|
||||||
memcpy(tex_pixels, b.pixels,
|
memcpy(tex_pixels, b.pixels,
|
||||||
SIM_WIDTH * SIM_HEIGHT * sizeof(uint32_t));
|
SIM_WIDTH * SIM_HEIGHT * sizeof(uint32_t));
|
||||||
SDL_UnlockTexture(tex);
|
SDL_UnlockTexture(tex);
|
||||||
// SDL_UpdateTexture(tex, NULL, b.pixels,SIM_WIDTH *
|
SDL_RenderCopy(ren, tex, NULL, &dst);
|
||||||
// sizeof(uint32_t));
|
SDL_RenderPresent(ren);
|
||||||
// SDL_RenderClear(ren);
|
b = !flags.multithread
|
||||||
SDL_RenderCopy(ren, tex, NULL, &dst);
|
? process_game(b)
|
||||||
SDL_RenderPresent(ren);
|
: process_game_mt(ta, b, threads, n_threads);
|
||||||
b = process_game(b);
|
}
|
||||||
// SDL_Delay(100);
|
frame_time = SDL_GetTicks() - frame_start;
|
||||||
|
if (frame_time < FRAME_DELAY)
|
||||||
|
SDL_Delay(FRAME_DELAY - frame_time);
|
||||||
}
|
}
|
||||||
SDL_DestroyTexture(tex);
|
SDL_DestroyTexture(tex);
|
||||||
SDL_DestroyRenderer(ren);
|
SDL_DestroyRenderer(ren);
|
||||||
SDL_DestroyWindow(win);
|
SDL_DestroyWindow(win);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
free_board(b);
|
free_board(b);
|
||||||
|
free(threads);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Board b = init_board(SIM_WIDTH, SIM_HEIGHT, 1);
|
Board b = init_board(SIM_WIDTH, SIM_HEIGHT, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user