Atomic Usage [Experimental]

This feature is unstable and behaviour depends on hardware and driver version/vendor.

Target functions

As target function for atomic it`s possible to use anonymous lambda functions.

1: 
2: 
3: 
4: 
<@
    fun (range: Range1D) (buffer: int clarray) ->
        atomic (+) buffer.[0] 1 |> ignore
@>

You can use quoted lambdas that inserted inside kernel quotation by splicing operator.

1: 
2: 
3: 
4: 
5: 
6: 
let f = <@ fun x y -> x + 2 * y @>

<@
    fun (range: Range1D) (buffer: int clarray) ->
        atomic %f buffer.[0] 1 |> ignore
@>

You cannot use arbitary named functions in atomic expressions, but you can use any named function, generally supported by Brahma.FSharp.

1: 
2: 
3: 
4: 
<@
    fun (range: Range1D) (buffer: int clarray) ->
        atomic min buffer.[0] 0 |> ignore
@>

There are some specific named functions, which can only be used as target function in atomic expression:

  • inc (only int, uint32, int64, uint64 supported)
  • dec (only int, uint32, int64, uint64 supported)
  • xchg (arbitary types supported)
  • cmpxchg (arbitary types supported)
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
<@
    fun (range: Range1D) (buffer: int clarray) ->
        atomic inc buffer.[0] |> ignore
@>

<@
    fun (range: Range1D) (buffer: bool clarray) ->
        atomic xchg buffer.[0] false |> ignore
@>

You can use srtp atomic functions in generic kernels. Following kernel can be used both with int and float32.

1: 
2: 
3: 
4: 
5: 
let inline kernel () =
    <@
        fun (range: Range1D) (result: 'a clarray) (value: 'a) ->
            atomic (+) result.[0] value |> ignore
    @>

Other rules

  • The first argument of target function must be te same type as return type of the function.
  • The first argument of target function must be od the form var or var.[expr] where var is variable in global or local memory.
  • You can use atomic functions inside other functions, but the first argument must be provided.
1: 
2: 
3: 
4: 
5: 
<@
    fun (range: Range1D) (buffer: int clarray) ->
        let g x = atomic (+) buffer.[0] x
        g 1 |> ignore
@>

But following kernels is not supported:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
<@
    fun (range: Range1D) (buffer: int clarray) ->
        // function without application of first parameter
        let g x y = atomic (+) x y
        g buffer.[0] 1 |> ignore
@>

<@
    fun (range: Range1D) (result: int clarray) ->
        // implicit argument
        let g = atomic (+) result.[0]
        g 1 |> ignore
@>

<@
    fun (range: Range1D) (result: int clarray) ->
        // function's argument in closure of target function
        let g y = atomic (fun x -> x + y + 1) result.[0]
        g 1 |> ignore
@>

Usage advices

Use

1: 
2: 
3: 
4: 
<@
    fun (range: Range1D) (buffer: int clarray) ->
        atomic (+) buffer.[0] 1 |> ignore
@>

instead of

1: 
2: 
3: 
4: 
<@
    fun (range: Range1D) (buffer: int clarray) ->
        atomic (fun x -> x + 1) buffer.[0] |> ignore
@>
namespace Brahma
namespace Brahma.FSharp
val range : Range1D
Multiple items
type Range1D =
  interface INDRange
  new : globalWorkSize:int -> Range1D
  new : globalWorkSize:int * localWorkSize:int -> Range1D
  private new : globalWorkSize:int * localWorkSize:int * __:unit -> Range1D
  member GlobalID0 : int
  member GlobalWorkSize : int
  member LocalID0 : int
  member LocalWorkSize : int
  static member CreateValid : neededSize:int * localWorkSize:int -> Range1D

--------------------
new : globalWorkSize:int -> Range1D
new : globalWorkSize:int * localWorkSize:int -> Range1D
val buffer : clarray<int>
Multiple items
val int : value:'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
type clarray<'a> = ClArray<'a>
val atomic : f:('a -> 'b) -> ('a -> 'b)
val ignore : value:'T -> unit
val f : Quotations.Expr<(int -> int -> int)>
val x : int
val y : int
val min : e1:'T -> e2:'T -> 'T (requires comparison)
val inc : p:'a -> 'a0 (requires member ( + ) and member get_One)
val buffer : clarray<bool>
type bool = System.Boolean
val xchg : p:'a -> value:'a -> 'a
val kernel : unit -> Quotations.Expr<(Range1D -> clarray<'a> -> 'a -> unit)> (requires member ( + ))
val result : clarray<'a> (requires member ( + ))
val value : 'a (requires member ( + ))
val g : (int -> int)
val g : (int -> int -> int)
val result : clarray<int>