#Parallel processing a loop
1 messages · Page 1 of 1 (latest)
like design multithreading for zig
We have threads in std
and a threadpool
but we can't help in any other way to make it so
Official website: https://softwareyoucan.love
Vancouver Conference Website: https://softwareyoucanlove.ca
Abstract:
When you hear that a project becomes parallel, you usually expect to see a speed boost. This isn't always true though. For those unaware, slapping on threads without much thought can easily make code slower. There's some impor...
You can @ us at any question you have for std.Thread stuff
std.Thread is the most likely thing that you will use for making this paralle
that and std.Thread.Pool
so we are receptive on any question you might have
lol
ah word you mean you won't banish me to the help channel
exactly
this is a fun topic, but is not as easy as in rust, importing a few libs, making a few things then hoping your design escaltes 😛
Or having a C macro that does it for you A-LA mpi
so this is mostly just a wiener-measuring contest (with myself) because it's already decently fast and i'm not sure how much faster it can realistically go
(i'm watching that talk rn btw)
Generally the recomendations is to get the max single threaded perf
then try to get a way to make it easy to multithread
all my time is spent in these two function calls
because for every particle in my array, i gotta compute those bad boys
i've used some physical reasoning to cut down the number of times i call them
but i'm not sure how much lower i can go
anyway, that's where i'm at
but i'm still very much a programming noob/boob
Can you do it in each individual thing?
honestly maybe it can't go faster
Not with the current formula, no
what does that mean
as in, are you calculating individually in every element?
yea
they are all independent otherwise?
i think so, yea
i say i think* because maybe there's some physical argument i can use to make this simpler
but currently, yea, each one needs its own calculation
this talk was good, but there's no code or examples
yeah, it's a thing to take into account
because here comes the good part
First, lets start with single thread performance
do you need to change EVERY particle position
or can you reduce the sample set to what is in front of you and visible
yea that's exactly the right question to ask
so i worked this out earlier
so yea, physical reasoning is for sure the way to go
well that's good to know, maybe i can think of some more optimizations by adding in some more assumptinos
but i think the good news is that i pretty much did this right
Yeah
Basically you try to squeeze perf before deciding creating threads is worth it
they are expensive thigns
i have expensive taste
After the question is yes, you would divide the data in some way that is easy to make the calculation in a way each particle is independent
if you can then you would do a previous step to separate in a broad range of interactions and reduce this interactions in parallel
as in, faster math to decide if an area is interacting then from there resolve only the interactions
interesting. i already do this
but i'll read that blog post
if you're ok with static chunking, here's an idea to try out:
fn join(
comptime func_a: anytype,
args_a: anytype,
comptime func_b: anytype,
args_b: anytype,
) !struct {
@TypeOf(@call(.auto, func_a, args_a)),
@TypeOf(@call(.auto, func_b, args_b)),
} {
const ArgsB = @TypeOf(args_b);
const RetB = @TypeOf(@call(.auto func_b, args_b));
const callback_b = struct {
fn callback(wg: *std.Thread.WaitGroup, args: ArgsB, ret: *RetB) void {
ret.* = @call(.auto, func_b, args);
wg.finish();
}
}.callback;
var ret_b: RetB = undefined;
var wg = std.Thread.WaitGroup{ .state = .{ .raw = 1 } };
try thread_pool.spawn(callback_b, .{ &wg, args_b, &ret_b });
const ret_a = @call(.auto, func_a, args_a);
thread_pool.waitAndWork(&wg);
return .{ ret_a, ret_b };
}
fn forEach(window: usize, slice: anytype, context: anytype) !void {
if (slice.len <= window) return context.handle(slice);
const mid = slice.len / 2;
_ = try join(
forEach, .{window, slice[0..mid], context},
forEach, .{window, slice[mid..], context},
);
}
I have to suppose the threadpool is a global?
yea, ideally there or tls
I'm curious; how much difference does it make to just both of these inline? (inline fn foo(...))
zero difference. i think the compiler must inline them already