Skip to content

UX: auto-transform captured seq to ptr UncheckedArray behind the scenes #179

Open
@mratsim

Description

@mratsim

having to cast[ptr UncheckedArray[T]] any captured seq[T] before use is a lot of boilerplate and quite annoying.

Example from Discord:

import std/[
  random,
  strutils,
  sequtils,
  sugar]
import chroma
import weave
import std/[times, monotimes]

randomize()
proc createColor() : string = 
  rand(0xFFFFFF).toHex(6)

proc main_serial(height, width: int) =
  var distance = newSeq[float64](height * width)

  # We create a power of 2 dataset so that indexing it is cheap and we measure processing speed.
  const pow2size = 8 # 2⁸ = 256
  let dataset = collect(for color in 0 ..< (1 shl pow2size): createColor())

  let start = getMonoTime()
  for upper in 0 ..< height:
    for lower in 0 ..< width:
      if upper == lower: 
        continue
      
      let colorUpper = parseHex(dataset[upper and (pow2size-1)]) # datasetAddr[upper mod pow2size]
      let colorLower = parseHex(dataset[lower and (pow2size-1)]) # datasetAddr[lower mod pow2size]
      distance[upper*width + lower] = distance(colorUpper, colorLower)
  let stop = getMonoTime()

  # echo distance.foldl(a+b)/distance.len.float
  echo "Time spent serial (ms): ", inMilliseconds(stop-start)

proc main_parallel(height, width: int) =
  var distance = newSeq[float64](height * width)

  # We create a power of 2 dataset so that indexing it is cheap and we measure processing speed.
  const pow2size = 8 # 2⁸ = 256
  let dataset = collect(for color in 0 ..< (1 shl pow2size): createColor())

  init(Weave)

  # Annoying ... to access seqs without causing GC issues
  let distanceAddr = cast[ptr UncheckedArray[float64]](distance[0].addr)
  let datasetAddr = cast[ptr UncheckedArray[string]](dataset[0].unsafeaddr)

  let start = getMonoTime()
  parallelFor upper in 0 ..< height:
    captures: {width, distanceAddr, datasetAddr}
    parallelFor lower in 0 ..< width:
      captures: {upper, width, distanceAddr, datasetAddr}
      if upper != lower: 
        let colorUpper = parseHex(datasetAddr[upper and (pow2size-1)]) # datasetAddr[upper mod pow2size]
        let colorLower = parseHex(datasetAddr[lower and (pow2size-1)]) # datasetAddr[lower mod pow2size]
        distanceAddr[upper*width + lower] = distance(colorUpper, colorLower)
  syncRoot(Weave)
  let stop = getMonoTime()

  # echo distance.foldl(a+b)/distance.len.float
  echo "Time spent parallel (ms): ", inMilliseconds(stop-start)

let height = 9600
let width = 1200

main_serial(height, width)
main_parallel(height, width)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions