Table of Contents
ex_parallel_for.c
n_parallel_for(): a loop over a range on several cores Fills an array in parallel and checks every item was written exactly once, whatever the slicing; that a small range runs on the caller alone; that an empty range does nothing; and that two parallel loops started at once from two threads, as workers of a pool do, both finish right while sharing one budget of cores. ```c
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
#include "nilorea/n_common.h" #include "nilorea/n_log.h" #include "nilorea/n_thread_pool.h"
static int failures = 0;
static void expect_true(const char* what, int ok) { if (!ok) { n_log(LOG_ERR, "FAIL: %s", what); failures++; } }
static void bump(size_t begin, size_t end, void* user) { int* items = (int*)user; size_t i = 0;
for (i = begin; i < end; i++) items[i]++;
}
static void* nested(void* arg) { n_parallel_for(0, 1000000, 1000, bump, arg); return NULL; }
static int all_ones(const int* items, size_t count) { size_t i = 0;
for (i = 0; i < count; i++)
if (items[i] != 1) return 0;
return 1;
}
int main(void) { int* a = NULL; int* b = NULL; pthread_t other; int slices = 0;
set_log_level(LOG_NOTICE);
a = calloc(1000000, sizeof(int));
b = calloc(1000000, sizeof(int));
if (!a || !b) return 1;
slices = n_parallel_for(0, 1000000, 1000, bump, a);
n_log(LOG_NOTICE, "ex_parallel_for: a million items in %d slice(s) on %ld core(s)", slices, get_nb_cpu_cores());
expect_true("every item written exactly once", all_ones(a, 1000000));
expect_true("more than one slice on a machine with more than one core",
get_nb_cpu_cores() < 2 || slices > 1);
memset(a, 0, 1000000 * sizeof(int));
expect_true("a range under two grains runs as one slice", n_parallel_for(0, 1500, 1000, bump, a) == 1);
expect_true("and does all of it", all_ones(a, 1500));
expect_true("an empty range does nothing", n_parallel_for(10, 10, 1, bump, a) == 0);
expect_true("a NULL function does nothing", n_parallel_for(0, 10, 1, NULL, a) == 0);
/* Two at once, sharing the budget. */
memset(a, 0, 1000000 * sizeof(int));
if (pthread_create(&other, NULL, nested, b) != 0) return 1;
n_parallel_for(0, 1000000, 1000, bump, a);
pthread_join(other, NULL);
expect_true("two loops at once both finish right", all_ones(a, 1000000) && all_ones(b, 1000000));
free(a);
free(b);
n_log(LOG_NOTICE, "ex_parallel_for: %s", failures ? "FAILED" : "ok");
return failures ? 1 : 0;
}
_Filename: ex_parallel_for.c_
Modules
- AABB3D
- ACCEPT_POOL
- ALLEGRO4
- ALLEGRO5
- ANIM_LIB
- ASTAR
- ATLAS_LIB
- AVRO
- CLOCK_SYNC
- COMMONS
- CONFIGFILE
- CYPHER_BASE64
- CYPHER_VIGENERE
- DEAD_RECKONING
- ENUMS
- EXCEPTIONS
- GAME_ENV
- GIT
- GUI
- HASH_TABLE
- ISOMETRIC_ENGINE
- LIST
- LOG
- LOGNODUP
- LZ4
- NETWORKING
- NETWORK_MSG
- N_COOKIES
- N_DIFF
- N_DIGEST
- N_DISK_CACHE
- N_DNS
- N_ECC
- N_ENTROPY
- N_FILES
- N_FLUIDS
- N_GUI_COLOR
- N_GUI_COLORWHEEL
- N_GUI_CURVE
- N_GUI_GRID
- N_GUI_POPUP
- N_HEX
- N_HTTP3
- N_HTTP_COOKIE
- N_HTTP_FORM
- N_HTTP_MIME
- N_HTTP_REQ
- N_HTTP_RESP
- N_HTTP_ROUTER
- N_HTTP_SERVER
- N_ICC
- N_JSON
- N_KAFKA
- N_LINALG
- N_MODULE
- N_OPENSSL_COMPAT
- N_PRETTY
- N_PTH
- N_QUERY
- N_RANDOM
- N_SHA256
- N_STR
- N_TIFF
- N_TIME
- N_USER
- N_X509
- N_ZIP
- PARTICLES
- PCRE
- PHYSICS
- SIGNALS
- STACK
- THREADS
- TRAJECTORY
- TREE
- ZLIB