@@ -5,10 +5,12 @@ open GraphBLAS.FSharp.Backend.Quotes
55open Microsoft.FSharp .Control
66open Microsoft.FSharp .Quotations
77open GraphBLAS.FSharp .Backend .Objects .ClContext
8- open GraphBLAS.FSharp .Backend .Objects .ClCell
98open GraphBLAS.FSharp .Backend .Objects .ArraysExtensions
109
1110module Reduce =
11+ /// <summary>
12+ /// Generalized reduction pattern.
13+ /// </summary>
1214 let private runGeneral ( clContext : ClContext ) workGroupSize scan scanToCell =
1315
1416 fun ( processor : MailboxProcessor < _ >) ( inputArray : ClArray < 'a >) ->
@@ -47,8 +49,8 @@ module Reduce =
4749 let result =
4850 scanToCell processor fstVertices verticesLength
4951
50- processor.Post ( Msg.CreateFreeMsg ( firstVerticesArray))
51- processor.Post ( Msg.CreateFreeMsg ( secondVerticesArray))
52+ firstVerticesArray.Free processor
53+ secondVerticesArray.Free processor
5254
5355 result
5456
@@ -129,6 +131,13 @@ module Reduce =
129131
130132 resultCell
131133
134+ /// <summary>
135+ /// Summarize array elements.
136+ /// </summary>
137+ /// <param name="clContext">ClContext.</param>
138+ /// <param name="workGroupSize">Work group size.</param>
139+ /// <param name="op">Summation operation.</param>
140+ /// <param name="zero">Neutral element for summation.</param>
132141 let sum ( clContext : ClContext ) workGroupSize op zero =
133142
134143 let scan = scanSum clContext workGroupSize op zero
@@ -226,6 +235,12 @@ module Reduce =
226235
227236 resultCell
228237
238+ /// <summary>
239+ /// Reduce an array of values.
240+ /// </summary>
241+ /// <param name="clContext">ClContext.</param>
242+ /// <param name="workGroupSize">Work group size.</param>
243+ /// <param name="op">Reduction operation.</param>
229244 let reduce ( clContext : ClContext ) workGroupSize op =
230245
231246 let scan = scanReduce clContext workGroupSize op
@@ -238,51 +253,79 @@ module Reduce =
238253
239254 fun ( processor : MailboxProcessor < _ >) ( array : ClArray < 'a >) -> run processor array
240255
256+ /// <summary>
257+ /// Reduction of an array of values by an array of keys.
258+ /// </summary>
241259 module ByKey =
260+ /// <summary>
261+ /// Reduce an array of values by key using a single work item.
262+ /// </summary>
263+ /// <param name="clContext">ClContext.</param>
264+ /// <param name="workGroupSize">Work group size.</param>
265+ /// <param name="reduceOp">Operation for reducing values.</param>
266+ /// <remarks>
267+ /// The length of the result must be calculated in advance.
268+ /// </remarks>
242269 let sequential ( clContext : ClContext ) workGroupSize ( reduceOp : Expr < 'a -> 'a -> 'a >) =
243270
244271 let kernel =
245272 <@ fun ( ndRange : Range1D ) length ( keys : ClArray < int >) ( values : ClArray < 'a >) ( reducedValues : ClArray < 'a >) ( reducedKeys : ClArray < int >) ->
246273
247274 let gid = ndRange.GlobalID0
248275
249- if gid = 0 then
250- let mutable currentKey = keys.[ 0 ]
251- let mutable segmentResult = values.[ 0 ]
252- let mutable segmentCount = 0
276+ if gid = 0 then
277+ let mutable currentKey = keys.[ 0 ]
278+ let mutable segmentResult = values.[ 0 ]
279+ let mutable segmentCount = 0
253280
254- for i in 1 .. length - 1 do
255- if currentKey = keys.[ i] then
256- segmentResult <- (% reduceOp) segmentResult values.[ i]
257- else
258- reducedValues.[ segmentCount] <- segmentResult
259- reducedKeys.[ segmentCount] <- currentKey
281+ for i in 1 .. length - 1 do
282+ if currentKey = keys.[ i] then
283+ segmentResult <- (% reduceOp) segmentResult values.[ i]
284+ else
285+ reducedValues.[ segmentCount] <- segmentResult
286+ reducedKeys.[ segmentCount] <- currentKey
260287
261- segmentCount <- segmentCount + 1
262- currentKey <- keys.[ i]
263- segmentResult <- values.[ i]
288+ segmentCount <- segmentCount + 1
289+ currentKey <- keys.[ i]
290+ segmentResult <- values.[ i]
264291
265- reducedKeys.[ segmentCount] <- currentKey
266- reducedValues.[ segmentCount] <- segmentResult @>
292+ reducedKeys.[ segmentCount] <- currentKey
293+ reducedValues.[ segmentCount] <- segmentResult @>
267294
268295 let kernel = clContext.Compile kernel
269296
270297 fun ( processor : MailboxProcessor < _ >) allocationMode ( resultLength : int ) ( keys : ClArray < int >) ( values : ClArray < 'a >) ->
271298
272- let reducedValues = clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
299+ let reducedValues =
300+ clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
273301
274- let reducedKeys = clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
302+ let reducedKeys =
303+ clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
275304
276- let ndRange = Range1D.CreateValid( resultLength, workGroupSize)
305+ let ndRange =
306+ Range1D.CreateValid( resultLength, workGroupSize)
277307
278308 let kernel = kernel.GetKernel()
279309
280- processor.Post( Msg.MsgSetArguments( fun () -> kernel.KernelFunc ndRange keys.Length keys values reducedValues reducedKeys))
310+ processor.Post(
311+ Msg.MsgSetArguments
312+ ( fun () -> kernel.KernelFunc ndRange keys.Length keys values reducedValues reducedKeys)
313+ )
281314
282315 processor.Post( Msg.CreateRunMsg<_, _>( kernel))
283316
284317 reducedKeys, reducedValues
285318
319+
320+ /// <summary>
321+ /// Reduces values by key. Each segment is reduced by one working item.
322+ /// </summary>
323+ /// <param name="clContext">ClContext.</param>
324+ /// <param name="workGroupSize">Work group size.</param>
325+ /// <param name="reduceOp">Operation for reducing values.</param>
326+ /// <remarks>
327+ /// The length of the result must be calculated in advance.
328+ /// </remarks>
286329 let segmentSequential ( clContext : ClContext ) workGroupSize ( reduceOp : Expr < 'a -> 'a -> 'a >) =
287330
288331 let kernel =
@@ -311,20 +354,45 @@ module Reduce =
311354
312355 fun ( processor : MailboxProcessor < _ >) allocationMode ( resultLength : int ) ( offsets : ClArray < int >) ( keys : ClArray < int >) ( values : ClArray < 'a >) ->
313356
314- let reducedValues = clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
357+ let reducedValues =
358+ clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
315359
316- let reducedKeys = clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
360+ let reducedKeys =
361+ clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
317362
318- let ndRange = Range1D.CreateValid( resultLength, workGroupSize)
363+ let ndRange =
364+ Range1D.CreateValid( resultLength, workGroupSize)
319365
320366 let kernel = kernel.GetKernel()
321367
322- processor.Post( Msg.MsgSetArguments( fun () -> kernel.KernelFunc ndRange resultLength keys.Length offsets keys values reducedValues reducedKeys))
368+ processor.Post(
369+ Msg.MsgSetArguments
370+ ( fun () ->
371+ kernel.KernelFunc
372+ ndRange
373+ resultLength
374+ keys.Length
375+ offsets
376+ keys
377+ values
378+ reducedValues
379+ reducedKeys)
380+ )
323381
324382 processor.Post( Msg.CreateRunMsg<_, _>( kernel))
325383
326384 reducedKeys, reducedValues
327385
386+ /// <summary>
387+ /// Reduces values by key. One working group participates in the reduction.
388+ /// </summary>
389+ /// <param name="clContext">ClContext.</param>
390+ /// <param name="workGroupSize">Work group size.</param>
391+ /// <param name="reduceOp">Operation for reducing values.</param>
392+ /// <remarks>
393+ /// Reduces an array of values that does not exceed the size of the workgroup.
394+ /// The length of the result must be calculated in advance.
395+ /// </remarks>
328396 let oneWorkGroupSegments ( clContext : ClContext ) workGroupSize ( reduceOp : Expr < 'a -> 'a -> 'a >) =
329397
330398 let kernel =
@@ -334,11 +402,15 @@ module Reduce =
334402
335403 // load values to local memory (may be without it)
336404 let localValues = localArray< 'a> workGroupSize
337- if lid < length then localValues.[ lid] <- values.[ lid]
405+
406+ if lid < length then
407+ localValues.[ lid] <- values.[ lid]
338408
339409 // load keys to local memory (mb without it)
340410 let localKeys = localArray< int> workGroupSize
341- if lid < length then localKeys.[ lid] <- keys.[ lid]
411+
412+ if lid < length then
413+ localKeys.[ lid] <- keys.[ lid]
342414
343415 // get unique keys bitmap
344416 let localBitmap = localArray< int> workGroupSize
@@ -377,19 +449,25 @@ module Reduce =
377449 let kernel = clContext.Compile kernel
378450
379451 fun ( processor : MailboxProcessor < _ >) allocationMode ( resultLength : int ) ( keys : ClArray < int >) ( values : ClArray < 'a >) ->
380- if keys.Length > workGroupSize then failwith " The length of the value should not exceed the size of the workgroup"
452+ if keys.Length > workGroupSize then
453+ failwith " The length of the value should not exceed the size of the workgroup"
381454
382- let reducedValues = clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
455+ let reducedValues =
456+ clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
383457
384- let reducedKeys = clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
458+ let reducedKeys =
459+ clContext.CreateClArrayWithSpecificAllocationMode( allocationMode, resultLength)
385460
386- let ndRange = Range1D.CreateValid( resultLength, workGroupSize)
461+ let ndRange =
462+ Range1D.CreateValid( resultLength, workGroupSize)
387463
388464 let kernel = kernel.GetKernel()
389465
390- processor.Post( Msg.MsgSetArguments( fun () -> kernel.KernelFunc ndRange keys.Length keys values reducedValues reducedKeys))
466+ processor.Post(
467+ Msg.MsgSetArguments
468+ ( fun () -> kernel.KernelFunc ndRange keys.Length keys values reducedValues reducedKeys)
469+ )
391470
392471 processor.Post( Msg.CreateRunMsg<_, _>( kernel))
393472
394473 reducedKeys, reducedValues
395-
0 commit comments