It's all rather funny.
First of all, if you're insisting on using `std/threadpool` and it so happens
that you use `--gc:orc` (or, like me, have it set in your config asthea
default) you get `SIGSEGV: Illegal storage access. (Attempt to read from
nil?)`. Arc is of course much **much** slower than refc due to this reckless
seq galore.
Also, it's rather hard for a beginner to deduce from the threadpool docs the
correct way to use it ("cast?", "so, should I `while` until I get -1 or no?").
Finally, I had to use `std/monotimes`, as `cpuTime` measurements for this code
outputs are completely off, which is probably expected, but not stressed enough
in the docs.
# nim c --threads:on -d:release --gc:arc stt.nim && time ./stt
import std/[threadpool, times, strutils, strformat, monotimes]
proc splitToTerms(n:int, k:int): seq[seq[int]] =
let kk = if k == 0: n else: k
if n != 0:
result = newSeq[seq[int]]()
if n <= kk:
result.add(@[n])
for i in 1 .. min(n, kk):
for l in splitToTerms(n-1, i):
result.add(l&(@[i]))
proc threaded(n:int): seq[int] =
var futures = newSeq[FlowVarBase](n)
let startTime = cpuTime()
let startMT = getMonoTime()
for i in 1..n: # indexing to keep ordering
futures[i-1] = spawn splitToTerms(n,i)
result = newSeq[int](n)
for _ in 1..n:
let futIdx = futures.blockUntilAny()
if futIdx != -1:
let r = ^cast[FlowVar[seq[seq[int]]]](futures[futIdx])
let dur = (getMonoTime() - startMT).inMilliseconds()
echo &"res#{futIdx+1} len={r.len} in {dur} ms"
result[futIdx] = r.len()
else:
break
const N=10
echo threaded(N)
Run