neighbour based algorithm for threads
It does seem to affect since sim falls into a "stable" configuration where cells rarely change quite quickly. I'm thinking of making a better colouring algorithm to see if I can get better images.
This commit is contained in:
12
src/base.h
12
src/base.h
@@ -30,6 +30,18 @@ typedef double f64;
|
|||||||
// 64 byte programs
|
// 64 byte programs
|
||||||
#define SIZEOF_PROGRAM (1LU << 6)
|
#define SIZEOF_PROGRAM (1LU << 6)
|
||||||
|
|
||||||
|
#define NUM_PROGRAMS_POW_2 17
|
||||||
|
#define NUM_PROGRAMS (1LU << NUM_PROGRAMS_POW_2)
|
||||||
|
#define SIMULATION_SIZE (SIZEOF_PROGRAM * NUM_PROGRAMS)
|
||||||
|
#define THREAD_POOL 4
|
||||||
|
|
||||||
|
// GUI stuff
|
||||||
|
#define WIDTH 800
|
||||||
|
#define HEIGHT 600
|
||||||
|
// Our grid will be of length sqrt(NUM_PROGRAMS). This is the same as
|
||||||
|
// 1LU<<(NUM_PROGRAMS_POW_2/2).
|
||||||
|
static const size_t GRID_WIDTH = 1LU << (NUM_PROGRAMS_POW_2 / 2);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Copyright (C) 2026 Aryadev Chavali
|
/* Copyright (C) 2026 Aryadev Chavali
|
||||||
|
|||||||
@@ -17,12 +17,6 @@
|
|||||||
#include "program_iter.h"
|
#include "program_iter.h"
|
||||||
#include "simulation.h"
|
#include "simulation.h"
|
||||||
|
|
||||||
#define WIDTH 800
|
|
||||||
#define HEIGHT 600
|
|
||||||
|
|
||||||
// Our grid will be of length sqrt(NUM_PROGRAMS). This is the same as
|
|
||||||
// 1LU<<(NUM_PROGRAMS_POW_2/2).
|
|
||||||
static const size_t GRID_WIDTH = 1LU << (NUM_PROGRAMS_POW_2 / 2);
|
|
||||||
static const size_t CELL_WIDTH = WIDTH / GRID_WIDTH;
|
static const size_t CELL_WIDTH = WIDTH / GRID_WIDTH;
|
||||||
|
|
||||||
static const char *VALID_OPS = "<>{}-+.,[]";
|
static const char *VALID_OPS = "<>{}-+.,[]";
|
||||||
|
|||||||
@@ -21,33 +21,71 @@ bool any_threads_using(const struct ThreadState *const states, u64 n)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_neighbours(u64 index, u64 ret[4])
|
||||||
|
{
|
||||||
|
memset(ret, 0xFF, sizeof(*ret) * 4);
|
||||||
|
u64 x = index / GRID_WIDTH;
|
||||||
|
u64 y = index % GRID_WIDTH;
|
||||||
|
u64 ptr = 0;
|
||||||
|
if (x > 0)
|
||||||
|
{
|
||||||
|
ret[ptr++] = ((x - 1) * GRID_WIDTH) + y;
|
||||||
|
}
|
||||||
|
if (x < GRID_WIDTH - 1)
|
||||||
|
{
|
||||||
|
ret[ptr++] = ((x + 1) * GRID_WIDTH) + y;
|
||||||
|
}
|
||||||
|
if (y > 0)
|
||||||
|
{
|
||||||
|
ret[ptr++] = (x * GRID_WIDTH) + (y + 1);
|
||||||
|
}
|
||||||
|
if (y < GRID_WIDTH - 1)
|
||||||
|
{
|
||||||
|
ret[ptr++] = (x * GRID_WIDTH) + (y - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void thread_pick(struct ThreadState *state)
|
void thread_pick(struct ThreadState *state)
|
||||||
{
|
{
|
||||||
struct Simulation *sim = state->sim;
|
struct Simulation *sim = state->sim;
|
||||||
|
u64 p1 = 0, p2 = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
u64 p1 = rand() % (SIMULATION_SIZE / SIZEOF_PROGRAM);
|
p1 = rand() % (SIMULATION_SIZE / SIZEOF_PROGRAM);
|
||||||
if (any_threads_using(sim->states, p1))
|
if (any_threads_using(sim->states, p1))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// TODO: Instead of picking a RANDOM p2, why not choose a neighbour of p1?
|
u64 neighbours[4];
|
||||||
// This way programs that are likely to replicate are replicating closer to
|
get_neighbours(p1, neighbours);
|
||||||
// themselves, and thus have a higher chance of further replication.
|
|
||||||
u64 p2 = rand() % (SIMULATION_SIZE / SIZEOF_PROGRAM);
|
u64 p2 = -1;
|
||||||
while (p1 * 8 <= ((p2 * 8) + SIZEOF_PROGRAM) &&
|
for (u64 i = 0; i < 4; ++i)
|
||||||
p2 * 8 <= ((p1 * 8) + SIZEOF_PROGRAM))
|
{
|
||||||
|
if (neighbours[i] == UINT64_MAX ||
|
||||||
|
any_threads_using(sim->states, neighbours[i]))
|
||||||
|
continue;
|
||||||
|
p2 = neighbours[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p2 < GRID_WIDTH)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise pick randomly.
|
||||||
|
p2 = rand() % (SIMULATION_SIZE / SIZEOF_PROGRAM);
|
||||||
|
while ((p1 * 8 <= ((p2 * 8) + SIZEOF_PROGRAM) &&
|
||||||
|
p2 * 8 <= ((p1 * 8) + SIZEOF_PROGRAM)) ||
|
||||||
|
any_threads_using(sim->states, p2))
|
||||||
{
|
{
|
||||||
p2 = rand() % (SIMULATION_SIZE / SIZEOF_PROGRAM);
|
p2 = rand() % (SIMULATION_SIZE / SIZEOF_PROGRAM);
|
||||||
}
|
}
|
||||||
if (any_threads_using(sim->states, p2))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
state->p1 = p1;
|
|
||||||
state->p2 = p2;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
state->p1 = p1;
|
||||||
|
state->p2 = p2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct timespec THREAD_DEFAULT_SLEEP = {.tv_sec = 1};
|
const struct timespec THREAD_DEFAULT_SLEEP = {.tv_sec = 1};
|
||||||
|
|||||||
@@ -12,12 +12,6 @@
|
|||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <threads.h>
|
#include <threads.h>
|
||||||
|
|
||||||
#define NUM_PROGRAMS_POW_2 10
|
|
||||||
#define NUM_PROGRAMS (1LU << NUM_PROGRAMS_POW_2)
|
|
||||||
#define SIMULATION_SIZE (SIZEOF_PROGRAM * NUM_PROGRAMS)
|
|
||||||
|
|
||||||
#define THREAD_POOL 8
|
|
||||||
|
|
||||||
struct ThreadState
|
struct ThreadState
|
||||||
{
|
{
|
||||||
u64 p1, p2;
|
u64 p1, p2;
|
||||||
|
|||||||
Reference in New Issue
Block a user