From 2f1c57e0ae5a9e9aedb3a5acbbeecae1c7ee1769 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Wed, 4 Mar 2026 21:28:32 -0500 Subject: [PATCH] raise concurrency cap for multi-cpu systems --- src/geo/slicer.js | 4 ++-- src/kiri/mode/fdm/work/slice.js | 8 ++++++++ src/kiri/run/minion.js | 19 ++++++++++++------- src/kiri/run/worker.js | 22 ++++++++++++---------- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/geo/slicer.js b/src/geo/slicer.js index 4889a8cb..9254ec69 100644 --- a/src/geo/slicer.js +++ b/src/geo/slicer.js @@ -41,6 +41,7 @@ export async function slice(points, options = {}) { zSum = 0.0, // sanity check that points enclose non-zere volume buckets = [], // banded/grouped faces to speed up slice/search overlapMax = options.overlap || 0.75, + bucketMin = options.bucketMin ?? 1, bucketMax = options.bucketMax || 100, onupdate = options.onupdate || function() {}, sliceFn = dval(options.slicer, sliceZ), @@ -138,7 +139,7 @@ export async function slice(points, options = {}) { let zSpan = zMax - zMin; let zSpanAvg = zSum / points.length; let bucketCount = options.bucket !== false ? - Math.min(bucketMax, Math.max(1, Math.floor(zSpan / zSpanAvg))) : 1; + Math.min(bucketMax, Math.max(bucketMin, Math.floor(zSpan / zSpanAvg))) : 1; zScale = 1 / (zMax / bucketCount); @@ -211,7 +212,6 @@ export async function slice(points, options = {}) { let count = 0; let opt = { ...options, zMin, zMax, zIndexes }; let ps = []; - for (let i = 0, l = buckets.length; i < l; i++) { let bucket = buckets[i]; let { points, slices } = bucket; diff --git a/src/kiri/mode/fdm/work/slice.js b/src/kiri/mode/fdm/work/slice.js index 1dafe0aa..3756d3f7 100644 --- a/src/kiri/mode/fdm/work/slice.js +++ b/src/kiri/mode/fdm/work/slice.js @@ -318,6 +318,10 @@ export function sliceOne(settings, widget, onupdate, ondone) { } } + if (isConcurrent) { + minions.setPoints(points); + } + // create Slice objects for specified list of Z heights // zGen() produces the list (or empty for slicer auto-detected) slice(points, { @@ -326,6 +330,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { xray: process.xray, zMin: bounds.min.z, zMax: bounds.max.z - zCut, + bucketMin: minions.concurrent * 5, union: controller.healMesh, indices: process.indices || process.xray, useAssembly, @@ -351,6 +356,9 @@ export function sliceOne(settings, widget, onupdate, ondone) { }) .then(decodeSlices) .then(processSlices) + .then(() => { + minions.setPoints([]); + }) .then(ondone); // z index generator (bottom up) diff --git a/src/kiri/run/minion.js b/src/kiri/run/minion.js index 0a229558..22cf938b 100644 --- a/src/kiri/run/minion.js +++ b/src/kiri/run/minion.js @@ -154,14 +154,11 @@ const funcs = self.minion = { sliceZ(data, seq) { debug('minion.sliceZ', { data, seq }); - let { z, points, options } = data; - let i = 0, p = 0, realp = new Array(points.length / 3); - while (i < points.length) { - realp[p++] = newPoint(points[i++], points[i++], points[i++]).round(3); - } + let { z, options } = data; + let { points } = cache; let state = { zero: [] }; let output = []; - sliceZ(z, realp, { + sliceZ(z, points, { ...options, each(out) { output.push(out) } }).then(() => { @@ -173,9 +170,17 @@ const funcs = self.minion = { }); }, + setPoints(data, seq) { + let { points } = data; + let i = 0, p = 0, realp = new Array(points.length / 3); + while (i < points.length) { + realp[p++] = newPoint(points[i++], points[i++], points[i++]).round(3); + } + cache.points = realp; + }, + putCache(msg) { const { key, data } = msg; - // log({ minion_putCache: key, data }); if (data) { cache[key] = data; } else { diff --git a/src/kiri/run/worker.js b/src/kiri/run/worker.js index 34594561..83c6620a 100644 --- a/src/kiri/run/worker.js +++ b/src/kiri/run/worker.js @@ -39,7 +39,7 @@ let drivers = { WJET }, ccvalue = self.navigator ? self.navigator.hardwareConcurrency || 0 : 0, - concurrent = Math.min(4, self.Worker && ccvalue > 3 ? ccvalue - 1 : 0), + concurrent = Math.round(Math.max(4, self.Worker && ccvalue > 3 ? ccvalue * 0.75 : 0)), current = { print: null, snap: null, @@ -174,6 +174,16 @@ const minwork = { } }, + setPoints(points) { + let i = 0, floatP = new Float32Array(points.length * 3); + for (let p of points) { + floatP[i++] = p.x; + floatP[i++] = p.y; + floatP[i++] = p.z; + } + minwork.broadcast("setPoints", { points: floatP }); + }, + // added functions (should be namespaced) subtract({ a, b, outA, outB, z, area, wasm }) { @@ -285,17 +295,9 @@ const minwork = { reject("concurrent slice unavaiable"); } let { each } = options; - // todo use shared array buffer? - let i = 0, floatP = new Float32Array(points.length * 3); - for (let p of points) { - floatP[i++] = p.x; - floatP[i++] = p.y; - floatP[i++] = p.z; - } minwork.queue({ cmd: "sliceZ", z, - points: floatP, options: codec.toCodable(options) }, data => { let recs = codec.decode(data.output); @@ -305,7 +307,7 @@ const minwork = { } } resolve(recs); - }, [ floatP.buffer ]); + }); }); }, };