{.experimental.}
import times
import threadpool
import future
let w = ["aaaaaaaaaa", "bbbbbbbbbb","cccccccccc"]
template parallelFor(
slice: Slice[int],
f:expr
) =
const a = slice.a
const b = slice.b
parallel:
for i in a..b: spawn f(i)
It works
parallelFor 0..2, (i:int) => echo i
This does not work: Error: cannot prove: i <= 2 (bounds check)
parallelFor 0..2, (i:int) => echo w[i]
Using pragma {.boundChecks: off.} does not help. How to write the code correctly?
You could not use the global GC value of "w" in a thread. So you have to make that const first of all.
Then going back to "basic" coding. This works:
# nim c --threads:on -d:release
{.experimental.}
import times
import threadpool
const w = ["aaaaaaaaaa", "bbbbbbbbbb","cccccccccc"]
template parallelFor(
slice: Slice[int],
f:expr
) =
const a = slice.a
const b = slice.b
parallel:
for i in a..b: spawn f(i)
proc doI(i: int) = echo w[i]
parallelFor(0..2, doI)
as does this (do syntax):
# nim c --threads:on -d:release --verbosity:0
{.experimental.}
import times
import threadpool
const w = ["aaaaaaaaaa", "bbbbbbbbbb","cccccccccc"]
template parallelFor(
slice: Slice[int],
f:expr
) =
const a = slice.a
const b = slice.b
parallel:
for i in a..b: spawn f(i)
parallelFor(0..2) do(i: int) {.closure.}: echo w[i]
Not sure if that is a compiler bug or limit to the => syntax but I can't find where to put the pragma.
Thank you very much for your help :-)
With the pragma {.closure.} now you can use the external variables in the template. But when you try to use my previous function (writeFile from this thread writeFile with iterator)
parallelFor(0..2) do(i: int) {.closure.}: writeFile("dict_" & $i & ".txt",enumerableRepeat(w[i], 3_000_000))
I get "Error: 'spawn' takes a GC safe call expression". To the compiler did not swear, I used the option --threadAnalysis:off
But is there any other way? Is it possible to make a template parallelFor (or iterator enumerableRepeat?) thread-safe?
Works for me...
# nim c --threads:on -d:release --verbosity:0
{.experimental.}
import times
import threadpool
proc enumerableRepeat[T](value: T, n: int = -1): iterator(): T {.gcsafe.} =
result = iterator(): T {.closure.} =
var i = 0
while n == -1 or i < n:
yield value
i += 1
proc writeFile[T](filePath: string, iter: iterator():T) =
var file = open(filePath, mode=fmWrite)
for str in iter(): file.writeLine(str)
file.close()
const w = ["aaaaaaaaaa", "bbbbbbbbbb","cccccccccc"]
template parallelFor(
slice: Slice[int],
f:expr
) =
const a = slice.a
const b = slice.b
parallel:
for i in a..b: spawn f(i)
#parallelFor(0..2) do(i: int) {.closure.}: echo w[i]
parallelFor(0..2) do(i: int) {.closure.}: writeFile("dict_" & $i & ".txt",enumerableRepeat(w[i], 3_000_000))