Congrats, that's really an achievement !

OpenMP is easy, you can use it like this, the following defines a new -d:openmp 
compilation flag:
    
    
    when defined(openmp):
      {.passC: "-fopenmp".}
      {.passL: "-fopenmp".}
    
    # Note: compile with stacktraces off or put
    # when defined(openmp): {.push stacktrace: off.}
    # and
    # when defined(openmp): {.pop.}
    # around OpenMP proc.
    # Heap allocation within a loop will crash OpenMP
    # Nim stacktraces allocate a string :/
    # Also avoid yourseq.add within an OpenMP loop as that could trigger the GC.
    # Preallocate and use yourseq[i] = foo
    
    var foo = newSeq[int](1000)
    
    {.push stacktrace: off.}
    for i in 0 || foo.len - 1:
      foo[i] = i
    {.pop.}
    
    # Alternatively
    
    {.push stacktrace: off.}
    for i in `||`(0, foo.len - 1, "simd if(ompsize > 500)"):
      foo[i] = i
    {.pop.}
    
    # simd will tell the compiler to use the SSE/AVX instructions
    # if(ompsize > 500) will only trigger OpenMP if the loop is bigger than 500
    # There are lots of other possibilities
    

Note that OpenMP is sometimes a bit of a hard beast to tame if you work on 
structures less than 64 bytes (the size of a cache line:

The work is split on several threads and threads should not work on the same 
variable (or use OpenMP atomics) and you might also encounter false 
sharing/cache invalidation: if you have an array of 8 integers, it fits in a 
cache line (64B), a thread trying to update it will invalidate the cache line 
for all other threads and ad repetitum. Result will be slower than single 
threaded. 

Reply via email to