tiny.simd.ThreadPool
Defined in thread.pool.
API (47)
Actions
Public operations.
Capacity.deriveCapacity.wasClampedautoTuneCompleteautoTuneCostscallerStatsconfigdeinitglobalWorkerIndexinitmaxThreadsnumThreadsFromCoresnumWorkersresetStatsrunrunWithCallersetWaitModestartstatsSnapshotwaitModewasClamped
Types and contracts
Public types and contracts.
Fields and members
Public fields and members.
addressblock_tunerbusycaller_statscapacityconfig_bitscurrent_begincurrent_tasksdoneepochexitinghandlesmappingspin_tunerstarted_threadsstatestatssynchronizationtask_callbacktask_contextwait_modework_availableworkers
Source
Source: lib/simd/src/thread/pool.zig:316
zig
pub const ThreadPool = struct { pub const State = enum(u8) { initialization, steady, teardown, }; pub const Capacity = struct { requested_threads: usize, threads: u8, workers: u8, pub fn derive(requested_threads: usize) Capacity { const supported = topology.haveThreadingSupport() and sys.thread.threadsSupported(); const thread_count: usize = if (supported) @min(requested_threads, max_threads) else 0; const worker_count: usize = thread_count + 1; return .{ .requested_threads = requested_threads, .threads = @intCast(thread_count), .workers = @intCast(worker_count), }; } pub fn wasClamped(self: Capacity) bool { return self.requested_threads != self.threads; } }; pub const StartError = sys.thread.SpawnError || error{ AlreadyDeinitialized, PoolMoved, }; pub const RunError = StartError || error{ Busy, InvalidRange, TooManyTasks, }; state: State = .initialization, capacity: Capacity, mapping: PoolWorkerMapping, address: usize = 0, wait_mode: std.atomic.Value(u8) = std.atomic.Value(u8).init(@backingInt(PoolWaitMode.block)), config_bits: std.atomic.Value(u16) = std.atomic.Value(u16).init((Config{ .wait_type = .block }).encode()), epoch: std.atomic.Value(u32) = std.atomic.Value(u32).init(0), work_available: std.atomic.Value(bool) = std.atomic.Value(bool).init(false), exiting: std.atomic.Value(bool) = std.atomic.Value(bool).init(false), busy: std.atomic.Value(bool) = std.atomic.Value(bool).init(false), synchronization: sys.thread.Mutex = .{}, done: sys.thread.Condition = .{}, started_threads: usize = 0, handles: [max_threads]sys.thread.JoinHandle = undefined, workers: [max_workers]Worker align(64) = @splat(.{}), task_context: *anyopaque = undefined, task_callback: Callback = undefined, current_begin: u64 = 0, current_tasks: usize = 0, stats: PoolStats = .{}, caller_stats: [max_callers]CallerStats = @splat(.{}), block_tuner: AutoTuner = .{}, spin_tuner: AutoTuner = .{}, pub fn init( requested_threads: usize, mapping: PoolWorkerMapping, ) ThreadPool { var self = ThreadPool{ .capacity = Capacity.derive(requested_threads), .mapping = mapping, }; var candidates: [max_configs]Config = undefined; self.block_tuner.setCandidates( Config.candidates(.block, &candidates), ) catch unreachable; self.spin_tuner.setCandidates( Config.candidates(.spin, &candidates), ) catch unreachable; self.config_bits.store( self.block_tuner.nextConfig().encode(), .monotonic, ); self.configureWorkers(); return self; } pub fn maxThreads() usize { if (!topology.haveThreadingSupport() or !sys.thread.threadsSupported()) { return 0; } var affinity = topology.LogicalProcessorSet{}; if (topology.getThreadAffinity(&affinity)) { const count = affinity.count(); if (count != 0) return @min(count - 1, max_threads); } return @min( topology.totalLogicalProcessors() -| 1, max_threads, ); } pub fn numThreadsFromCores( allocator: std.mem.Allocator, ) std.mem.Allocator.Error!usize { if (!topology.haveThreadingSupport() or !sys.thread.threadsSupported()) { return 0; } var detected = try topology.init(allocator); defer detected.deinit(allocator); if (detected.packages.len == 0) return maxThreads(); return @min(detected.packages[0].cores.len -| 1, max_threads); } pub fn start(self: *ThreadPool) StartError!void { if (self.state == .teardown) return error.AlreadyDeinitialized; if (self.state == .steady) { try self.requireStableAddress(); return; } self.address = @intFromPtr(self); if (self.capacity.threads == 0) { self.state = .steady; return; } var spawned: usize = 0; while (spawned < self.capacity.threads) : (spawned += 1) { self.handles[spawned] = sys.thread.spawn(workerMain, .{ WorkerContext{ .pool = self, .worker_index = spawned + 1, }, }) catch |err| { self.stopSpawned(spawned); return err; }; nameWorker(self.handles[spawned], spawned); } self.synchronization.lock(); while (self.started_threads != self.capacity.threads) { self.done.wait(&self.synchronization); } self.synchronization.unlock(); self.state = .steady; } pub fn deinit(self: *ThreadPool) void { if (self.state == .teardown) return; if (self.state == .initialization) { self.state = .teardown; self.address = 0; return; } self.requireStableAddress() catch unreachable; std.debug.assert(!self.busy.load(.acquire)); if (self.capacity.threads != 0) { self.signalExit(); for (self.handles[0..self.capacity.threads]) |handle| { handle.join(); } } self.state = .teardown; self.address = 0; } pub fn numWorkers(self: *const ThreadPool) usize { return self.capacity.workers; } pub fn wasClamped(self: *const ThreadPool) bool { return self.capacity.wasClamped(); } pub fn setWaitMode( self: *ThreadPool, mode: PoolWaitMode, ) (error{Busy} || StartError)!void { if (self.state == .teardown) return error.AlreadyDeinitialized; if (self.busy.cmpxchgStrong( false, true, .acquire, .monotonic, ) != null) return error.Busy; defer self.busy.store(false, .release); self.wait_mode.store(@backingInt(mode), .release); const mode_tuner = self.tuner(mode); const selected = mode_tuner.best() orelse mode_tuner.nextConfig(); self.config_bits.store(selected.encode(), .release); if (self.state == .steady and self.capacity.threads != 0) { try self.requireStableAddress(); const epoch = self.wakeWorkers(false, true); self.waitForWorkers(epoch); } } pub fn waitMode(self: *const ThreadPool) PoolWaitMode { return @fromBackingInt(@intCast(self.wait_mode.load(.acquire))); } pub fn config(self: *const ThreadPool) Config { return Config.decode(self.config_bits.load(.acquire)); } pub fn autoTuneComplete(self: *const ThreadPool) bool { return self.tunerConst(self.waitMode()).best() != null; } pub fn autoTuneCosts(self: *ThreadPool) []autotune.CostDistribution { return self.tuner(self.waitMode()).costs(); } pub fn statsSnapshot(self: *ThreadPool) PoolStats { self.synchronization.lock(); defer self.synchronization.unlock(); return self.stats; } pub fn callerStats( self: *ThreadPool, caller: Caller, ) ?CallerStats { if (caller.index >= max_callers) return null; self.synchronization.lock(); defer self.synchronization.unlock(); return self.caller_stats[caller.index]; } pub fn resetStats(self: *ThreadPool) error{Busy}!void { if (self.busy.cmpxchgStrong( false, true, .acquire, .monotonic, ) != null) return error.Busy; defer self.busy.store(false, .release); self.synchronization.lock(); defer self.synchronization.unlock(); self.stats = .{}; self.caller_stats = @splat(.{}); } pub fn globalWorkerIndex( self: *const ThreadPool, local_worker_index: usize, ) error{WorkerOutOfBounds}!usize { if (local_worker_index >= self.numWorkers()) { return error.WorkerOutOfBounds; } return self.mapping.globalIndex(local_worker_index); } pub fn run( self: *ThreadPool, begin: u64, end: u64, context: anytype, comptime body: fn (@TypeOf(context), u64, usize) void, ) RunError!void { return self.runWithCaller(begin, end, .{}, context, body); } pub fn runWithCaller( self: *ThreadPool, begin: u64, end: u64, caller: Caller, context: anytype, comptime body: fn (@TypeOf(context), u64, usize) void, ) RunError!void { if (begin > end) return error.InvalidRange; const task_count_u64 = end - begin; if (task_count_u64 > std.math.maxInt(usize)) { return error.TooManyTasks; } const task_count: usize = @intCast(task_count_u64); const Context = @TypeOf(context); const Adapter = CallbackAdapter(Context, body); var context_storage = context; const started_ns = nowNanoseconds(); if (task_count <= 1 or self.numWorkers() == 1) { var task = begin; while (task < end) : (task += 1) body(context, task, 0); self.recordRun( caller, task_count, false, 0, elapsedNanoseconds(started_ns), ); return; } if (self.busy.cmpxchgStrong( false, true, .acquire, .monotonic, ) != null) return error.Busy; defer self.busy.store(false, .release); try self.start(); try self.requireStableAddress(); self.task_context = @ptrCast(&context_storage); self.task_callback = Adapter.call; self.current_begin = begin; self.current_tasks = task_count; self.divideRange(begin, end); for (self.workers[0..self.numWorkers()]) |*worker| { worker.last_tasks = 0; worker.last_stolen = 0; } const epoch = self.wakeWorkers( true, self.config().wait_type == .block, ); self.runWorker(0); self.waitForWorkers(epoch); var stolen_tasks: usize = 0; for (self.workers[0..self.numWorkers()]) |worker| { stolen_tasks += worker.last_stolen; } const elapsed_ns = elapsedNanoseconds(started_ns); self.recordRun( caller, task_count, true, stolen_tasks, elapsed_ns, ); self.notifyAutotune(elapsed_ns); } fn configureWorkers(self: *ThreadPool) void { const worker_count: u32 = self.capacity.workers; for (self.workers[0..worker_count], 0..) |*worker, worker_index| { worker.* = .{}; worker.victim_count = @intCast(@min(max_victims, worker_count)); const coprime = ShuffledIota.findAnotherCoprime( worker_count, @intCast((worker_index + 1) * 257 + worker_index * 13), ); const shuffled = ShuffledIota.init(coprime); worker.victims[0] = @intCast(worker_index); for (1..worker.victim_count) |victim_index| { worker.victims[victim_index] = @intCast(shuffled.next( worker.victims[victim_index - 1], worker_count, )); } } } fn divideRange(self: *ThreadPool, begin: u64, end: u64) void { for (self.workers[0..self.numWorkers()], 0..) |*worker, index| { const range = workerRange( 0, end - begin, self.numWorkers(), index, ) catch unreachable; worker.begin.store(@intCast(range.begin), .monotonic); worker.end = @intCast(range.end); } } fn runWorker(self: *ThreadPool, worker_index: usize) void { var task_count: usize = 0; var stolen_count: usize = 0; if (self.current_tasks <= self.numWorkers()) { const offset = self.workers[0].begin.load(.monotonic) + worker_index; const end = self.workers[self.numWorkers() - 1].end; if (offset < end) { self.task_callback( self.task_context, self.current_begin + offset, worker_index, ); task_count = 1; } } else { const worker = &self.workers[worker_index]; for (worker.victims[0..worker.victim_count]) |victim_index| { const victim = &self.workers[victim_index]; while (true) { const offset = victim.begin.fetchAdd(1, .monotonic); if (offset >= victim.end) break; self.task_callback( self.task_context, self.current_begin + offset, worker_index, ); task_count += 1; stolen_count += @intFromBool(victim_index != worker_index); } } } self.workers[worker_index].last_tasks = task_count; self.workers[worker_index].last_stolen = stolen_count; } fn wakeWorkers( self: *ThreadPool, work_available: bool, wake_blocked: bool, ) u32 { self.work_available.store(work_available, .monotonic); const epoch = self.epoch.load(.monotonic) +% 1; self.epoch.store(epoch, .release); for (self.workers[1..self.numWorkers()]) |*worker| { worker.wait_epoch.store(epoch, .release); } if (wake_blocked and self.capacity.threads != 0) { wait.wakeAll(&self.workers[1].wait_epoch); } return epoch; } fn waitForWorkers(self: *ThreadPool, epoch: u32) void { spin.callWithSpin( self.config().spin_type, BarrierContext{ .pool = self, .epoch = epoch }, waitAtBarrier, ); } fn waitForWork( self: *ThreadPool, worker_index: usize, observed_epoch: u32, ) ?u32 { while (true) { if (self.exiting.load(.acquire)) return null; const config_value = self.config(); switch (config_value.wait_type) { .block => { const next_epoch = wait.blockUntilDifferent( observed_epoch, &self.workers[1].wait_epoch, ); if (self.exiting.load(.acquire)) return null; return next_epoch; }, .spin_shared, .spin_separate => { const watched = if (config_value.wait_type == .spin_separate) &self.workers[worker_index].wait_epoch else &self.epoch; var next_epoch: u32 = observed_epoch; spin.callWithSpin( config_value.spin_type, SpinWaitContext{ .previous = observed_epoch, .watched = watched, .next = &next_epoch, }, waitUntilDifferent, ); if (self.exiting.load(.acquire)) return null; return next_epoch; }, } } } fn workerStarted(self: *ThreadPool) void { self.synchronization.lock(); self.started_threads += 1; self.done.broadcast(); self.synchronization.unlock(); } fn workerReached(self: *ThreadPool, worker_index: usize, epoch: u32) void { self.workers[worker_index].barrier_epoch.store(epoch, .release); } fn stopSpawned(self: *ThreadPool, spawned: usize) void { self.signalExit(); for (self.handles[0..spawned]) |handle| handle.join(); self.exiting.store(false, .monotonic); self.epoch.store(0, .monotonic); self.started_threads = 0; self.address = 0; self.work_available.store(false, .monotonic); self.configureWorkers(); } fn signalExit(self: *ThreadPool) void { self.exiting.store(true, .release); const epoch = self.epoch.load(.monotonic) +% 1; self.epoch.store(epoch, .release); for (self.workers[1..self.numWorkers()]) |*worker| { worker.wait_epoch.store(epoch, .release); } if (self.capacity.threads != 0) { wait.wakeAll(&self.workers[1].wait_epoch); } } fn requireStableAddress(self: *const ThreadPool) error{PoolMoved}!void { if (self.address != @intFromPtr(self)) return error.PoolMoved; } fn recordRun( self: *ThreadPool, caller: Caller, tasks: usize, threaded: bool, stolen_tasks: usize, elapsed_ns: u64, ) void { self.synchronization.lock(); defer self.synchronization.unlock(); self.stats.runs +|= 1; self.stats.serial_runs +|= @intFromBool(!threaded); self.stats.threaded_runs +|= @intFromBool(threaded); self.stats.tasks +|= tasks; self.stats.stolen_tasks +|= stolen_tasks; self.stats.elapsed_ns +|= elapsed_ns; const caller_index = if (caller.index < max_callers) caller.index else 0; const stats = &self.caller_stats[caller_index]; stats.runs +|= 1; stats.tasks +|= tasks; stats.workers +|= if (threaded) self.numWorkers() else 1; stats.elapsed_ns +|= elapsed_ns; } fn notifyAutotune(self: *ThreadPool, elapsed_ns: u64) void { const mode = self.waitMode(); const selected = blk: { const tuner_value = self.tuner(mode); if (tuner_value.best()) |best| break :blk best.*; tuner_value.notifyCost(@max(elapsed_ns, 1)); break :blk if (tuner_value.best()) |best| best.* else tuner_value.nextConfig().*; }; self.config_bits.store(selected.encode(), .release); } fn tuner(self: *ThreadPool, mode: PoolWaitMode) *AutoTuner { return switch (mode) { .block => &self.block_tuner, .spin => &self.spin_tuner, }; } fn tunerConst(self: *const ThreadPool, mode: PoolWaitMode) *const AutoTuner { return switch (mode) { .block => &self.block_tuner, .spin => &self.spin_tuner, }; }};Source: lib/simd/src/root.zig:136
zig
pub const ThreadPool = thread.ThreadPool;Also reachable as
Complete caller list for ThreadPool.deinit
13 direct callers.
lib.http.src.profiling.pool.dispatchBounded[function] — private source atlib/http/src/profiling/pool.zig:20in nearest public ownerlib.http.src.profiling.pooltiny.http.Server.deinit[method] atlib/http/src/server/runtime.zig:197tiny.http.Server.init[function] atlib/http/src/server/runtime.zig:91lib.simd.src.thread.pool.outerTask[function] — private source atlib/simd/src/thread/pool.zig:1342in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_live_pools_switch_wait_modes_repeatedly[function] — test source atlib/simd/src/thread/pool.zig:1394in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_autotuning_visits_candidates_and_converges[function] — test source atlib/simd/src/thread/pool.zig:1418in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_clamps_capacity_and_rejects_invalid_ranges[function] — test source atlib/simd/src/thread/pool.zig:1442in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_wait_modes_preserve_the_task_sum_and_caller_statistics[function] — test source atlib/simd/src/thread/pool.zig:1277in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_worker_mapping_preserves_local_and_cluster_indices[function] — test source atlib/simd/src/thread/pool.zig:1128in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pools_reuse_shifted_ranges_and_allow_nested_serial_runs[function] — test source atlib/simd/src/thread/pool.zig:1351in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_small_assignments_retain_valid_worker_identities[function] — test source atlib/simd/src/thread/pool.zig:1246in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_preserves_ranges_near_the_u64_limit[function] — test source atlib/simd/src/thread/pool.zig:1202in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_runs_every_task_once_in_block_and_spin_modes[function] — test source atlib/simd/src/thread/pool.zig:1171in nearest public ownertiny.simd.thread.pool
Complete caller list for ThreadPool.init
12 direct callers.
lib.http.src.profiling.pool.dispatchBounded[function] — private source atlib/http/src/profiling/pool.zig:20in nearest public ownerlib.http.src.profiling.pooltiny.http.Server.init[function] atlib/http/src/server/runtime.zig:91lib.simd.src.thread.pool.outerTask[function] — private source atlib/simd/src/thread/pool.zig:1342in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_live_pools_switch_wait_modes_repeatedly[function] — test source atlib/simd/src/thread/pool.zig:1394in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_autotuning_visits_candidates_and_converges[function] — test source atlib/simd/src/thread/pool.zig:1418in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_clamps_capacity_and_rejects_invalid_ranges[function] — test source atlib/simd/src/thread/pool.zig:1442in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_wait_modes_preserve_the_task_sum_and_caller_statistics[function] — test source atlib/simd/src/thread/pool.zig:1277in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_worker_mapping_preserves_local_and_cluster_indices[function] — test source atlib/simd/src/thread/pool.zig:1128in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pools_reuse_shifted_ranges_and_allow_nested_serial_runs[function] — test source atlib/simd/src/thread/pool.zig:1351in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_small_assignments_retain_valid_worker_identities[function] — test source atlib/simd/src/thread/pool.zig:1246in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_preserves_ranges_near_the_u64_limit[function] — test source atlib/simd/src/thread/pool.zig:1202in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_runs_every_task_once_in_block_and_spin_modes[function] — test source atlib/simd/src/thread/pool.zig:1171in nearest public ownertiny.simd.thread.pool
Complete caller list for ThreadPool.maxThreads
8 direct callers.
tiny.simd.ThreadPool.numThreadsFromCores[function] atlib/simd/src/thread/pool.zig:426lib.simd.src.thread.pool.test_Highway_live_pools_switch_wait_modes_repeatedly[function] — test source atlib/simd/src/thread/pool.zig:1394in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_autotuning_visits_candidates_and_converges[function] — test source atlib/simd/src/thread/pool.zig:1418in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_wait_modes_preserve_the_task_sum_and_caller_statistics[function] — test source atlib/simd/src/thread/pool.zig:1277in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pools_reuse_shifted_ranges_and_allow_nested_serial_runs[function] — test source atlib/simd/src/thread/pool.zig:1351in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_small_assignments_retain_valid_worker_identities[function] — test source atlib/simd/src/thread/pool.zig:1246in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_preserves_ranges_near_the_u64_limit[function] — test source atlib/simd/src/thread/pool.zig:1202in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_runs_every_task_once_in_block_and_spin_modes[function] — test source atlib/simd/src/thread/pool.zig:1171in nearest public ownertiny.simd.thread.pool
Complete caller list for ThreadPool.numWorkers
9 direct callers.
lib.simd.src.thread.pool.ThreadPool.divideRange[method] — private source atlib/simd/src/thread/pool.zig:677in nearest public ownertiny.simd.thread.pooltiny.simd.ThreadPool.globalWorkerIndex[method] atlib/simd/src/thread/pool.zig:568lib.simd.src.thread.pool.ThreadPool.recordRun[method] — private source atlib/simd/src/thread/pool.zig:829in nearest public ownertiny.simd.thread.pooltiny.simd.ThreadPool.runWithCaller[method] atlib/simd/src/thread/pool.zig:588lib.simd.src.thread.pool.ThreadPool.runWorker[method] — private source atlib/simd/src/thread/pool.zig:690in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_clamps_capacity_and_rejects_invalid_ranges[function] — test source atlib/simd/src/thread/pool.zig:1442in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_wait_modes_preserve_the_task_sum_and_caller_statistics[function] — test source atlib/simd/src/thread/pool.zig:1277in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_worker_mapping_preserves_local_and_cluster_indices[function] — test source atlib/simd/src/thread/pool.zig:1128in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_small_assignments_retain_valid_worker_identities[function] — test source atlib/simd/src/thread/pool.zig:1246in nearest public ownertiny.simd.thread.pool
Complete caller list for ThreadPool.run
8 direct callers.
lib.simd.src.thread.pool.outerTask[function] — private source atlib/simd/src/thread/pool.zig:1342in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_live_pools_switch_wait_modes_repeatedly[function] — test source atlib/simd/src/thread/pool.zig:1394in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_autotuning_visits_candidates_and_converges[function] — test source atlib/simd/src/thread/pool.zig:1418in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pool_clamps_capacity_and_rejects_invalid_ranges[function] — test source atlib/simd/src/thread/pool.zig:1442in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_pools_reuse_shifted_ranges_and_allow_nested_serial_runs[function] — test source atlib/simd/src/thread/pool.zig:1351in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_small_assignments_retain_valid_worker_identities[function] — test source atlib/simd/src/thread/pool.zig:1246in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_preserves_ranges_near_the_u64_limit[function] — test source atlib/simd/src/thread/pool.zig:1202in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.test_Highway_thread_pool_runs_every_task_once_in_block_and_spin_modes[function] — test source atlib/simd/src/thread/pool.zig:1171in nearest public ownertiny.simd.thread.pool
Complete call list for ThreadPool.runWithCaller
13 direct calls.
lib.simd.src.thread.pool.CallbackAdapter[function] — private source atlib/simd/src/thread/pool.zig:938in nearest public ownertiny.simd.thread.pooltiny.simd.ThreadPool.config[method] atlib/simd/src/thread/pool.zig:526lib.simd.src.thread.pool.ThreadPool.divideRange[method] — private source atlib/simd/src/thread/pool.zig:677in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.ThreadPool.notifyAutotune[method] — private source atlib/simd/src/thread/pool.zig:856in nearest public ownertiny.simd.thread.pooltiny.simd.ThreadPool.numWorkers[method] atlib/simd/src/thread/pool.zig:491lib.simd.src.thread.pool.ThreadPool.recordRun[method] — private source atlib/simd/src/thread/pool.zig:829in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.ThreadPool.requireStableAddress[method] — private source atlib/simd/src/thread/pool.zig:825in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.ThreadPool.runWorker[method] — private source atlib/simd/src/thread/pool.zig:690in nearest public ownertiny.simd.thread.pooltiny.simd.ThreadPool.start[method] atlib/simd/src/thread/pool.zig:440lib.simd.src.thread.pool.ThreadPool.waitForWorkers[method] — private source atlib/simd/src/thread/pool.zig:743in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.ThreadPool.wakeWorkers[method] — private source atlib/simd/src/thread/pool.zig:726in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.elapsedNanoseconds[function] — private source atlib/simd/src/thread/pool.zig:958in nearest public ownertiny.simd.thread.poollib.simd.src.thread.pool.nowNanoseconds[function] — private source atlib/simd/src/thread/pool.zig:954in nearest public ownertiny.simd.thread.pool
Audit
| Definitions | 25 |
|---|---|
| Public names | 75 |
| Members | 29 |
| Version | 26.7.0 |
| Revision | daab053ee433 |