I have some working code and I'm experimenting with using pointers and slices to achieve the same results.

Here's what I conceptually want to do.

  parallel:
    for bytn in 0..bprg-1:
      .....
      var seg_r: seq[uint8] = seg[bytn*Ks..byt*Ks+Ks-1]
      spawn residue_sieve(n_row, seg_r, Kmax, Ks, bytn)
  sync()t

I want to pass seg_r as a slice, but the compiler squawks with this (it never asked me if I can verify its all good ), even when I compile with --boundChecks:on|off.

ssozp13x1d7bparnew512.nim(192, 40) Error: cannot prove: bytn * Ks <= len(seg) + -1 (bounds check)

So I have seg a seq[uint8](m * Ks) array, and I'm processing each of the m rows in parallel.

When I pass in let row_i = bytn * Ks it r/w fine doing seg[row_i + k] inside residue_sieve.

I'm trying to understand how to do the following cases:

1) define seg_r as a slice in seg I can read/write each element to as seg_r[k] in residue_sieve.

2) define seg_r as pointer to start of slice at seg[bytn*Ks] and r/w as seg_r[k] in residue_sieve.

3) define seg_r as pointer to slice seg[bytn*Ks..bytn*Ks+Ks-1] and r/w as ....

I'm doing this to compare timing differences between them in my code (want fastest).

2017-12-02 23:00:34

Don't forget that Nim seqs are copy on assignment

If you want slices that share memory you will have to use shallowCopy similar to the following:

var seg_r: seq[uint8]
shallowCopy(seg_r, seg[slice])

seg[slice] might be creating a copy as well so maybe checked what is done in this PR to introduce views/slices of seq.

2017-12-03 12:18:34

@jzakiya Too bad there is no seq constructor from raw pointer and size. This way, you could just make seq which is, in fact, a view of another seq. Hypothetical example:

var s = @[3,1,4,1,5,9,2]
var v = ptrToSeq(s[2].addr, 3)
assert(v == @[4,1,5])
s[2] = 2
assert(v == @[2,1,5])

2017-12-03 19:29:57

Seqs own the data they contain, views don't, conceptually there is no safe way to create a seq from a view without a copy.

You can pass zero-copy slices in a parallel statement https://nim-lang.org/docs/manual.html#parallel-spawn-parallel-statement if the parameter is of type openArray.

Slices are optimized so that no copy is performed.

tests/parallel/tparfind.nim has an example:

discard """
  output: "500"
"""

import threadpool, sequtils

{.experimental.}

proc linearFind(a: openArray[int]; x, offset: int): int =
  for i, y in a:
    if y == x: return i+offset
  result = -1

proc parFind(a: seq[int]; x: int): int =
  var results: array[4, int]
  parallel:
    if a.len >= 4:
      let chunk = a.len div 4
      results[0] = spawn linearFind(a[0 ..< chunk], x, 0)
      results[1] = spawn linearFind(a[chunk ..< chunk*2], x, chunk)
      results[2] = spawn linearFind(a[chunk*2 ..< chunk*3], x, chunk*2)
      results[3] = spawn linearFind(a[chunk*3 ..< a.len], x, chunk*3)
  result = max(results)


let data = toSeq(0..1000)
echo parFind(data, 500)

2017-12-03 21:44:41
@Araq Do you mean the slices have to be passed directly, without a local binding? 2017-12-06 22:41:46
That is correct, yes. 2017-12-06 23:37:14
@Araq Thank you, I didn't know that (I don't really use Nim's parallel capabilities). That's something new for me, especially comparing to how it works in, say, Rust. 2017-12-08 17:47:38