forked from SparseLinearAlgebra/GraphBLAS-sharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOperations.fs
543 lines (477 loc) · 25.6 KB
/
Operations.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
namespace GraphBLAS.FSharp
open Brahma.FSharp
open Microsoft.FSharp.Core
open Microsoft.FSharp.Quotations
open GraphBLAS.FSharp.Objects
open GraphBLAS.FSharp.Objects.ClContextExtensions
open GraphBLAS.FSharp.Backend.Matrix
open GraphBLAS.FSharp.Backend.Vector
open GraphBLAS.FSharp.Backend.Operations
[<RequireQualifiedAccess>]
module Operations =
module Vector =
/// <summary>
/// Builds a new vector whose elements are the results of applying the given function
/// to each of the elements of the vector.
/// </summary>
/// <param name="op">
/// A function to transform values of the input vector.
/// Operand and result types should be optional to distinguish explicit and implicit zeroes.
/// </param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map (op: Expr<'a option -> 'b option>) (clContext: ClContext) workGroupSize =
let mapSparse =
Sparse.Vector.map op clContext workGroupSize
let mapDense =
Dense.Vector.map op clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode matrix ->
match matrix with
| ClVector.Sparse v ->
mapSparse processor allocationMode v
|> ClVector.Sparse
| ClVector.Dense v ->
mapDense processor allocationMode v
|> ClVector.Dense
/// <summary>
/// Builds a new vector whose values are the results of applying the given function
/// to the corresponding pairs of values from the two vectors.
/// </summary>
/// <param name="op">
/// A function to transform pairs of values from the input vectors.
/// Operands and result types should be optional to distinguish explicit and implicit zeroes.
/// </param>
/// <remarks>
/// Formats of the given vectors should match, otherwise an exception will be thrown.
/// </remarks>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2 (op: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize =
let map2Dense =
Dense.Vector.map2 op clContext workGroupSize
let map2Sparse =
Sparse.Vector.map2 op clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) ->
match leftVector, rightVector with
| ClVector.Dense left, ClVector.Dense right ->
map2Dense processor allocationMode left right
|> ClVector.Dense
|> Some
| ClVector.Sparse left, ClVector.Sparse right ->
Option.map ClVector.Sparse (map2Sparse processor allocationMode left right)
| _ -> failwith "Vector formats are not matching."
/// <summary>
/// Builds a new vector whose values are the results of applying the given function
/// to the corresponding pairs of values from the two vectors.
/// </summary>
/// <param name="op">
/// A function to transform pairs of values from the input vectors.
/// Operation assumption: one of the operands should always be non-zero.
/// </param>
/// <remarks>
/// Formats of the given vectors should match, otherwise an exception will be thrown.
/// </remarks>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2AtLeastOne (op: Expr<AtLeastOne<'a, 'b> -> 'c option>) (clContext: ClContext) workGroupSize =
let map2Sparse =
Sparse.Vector.map2AtLeastOne op clContext workGroupSize
let map2Dense =
Dense.Vector.map2AtLeastOne op clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) ->
match leftVector, rightVector with
| ClVector.Sparse left, ClVector.Sparse right ->
Option.map ClVector.Sparse (map2Sparse processor allocationMode left right)
| ClVector.Dense left, ClVector.Dense right ->
map2Dense processor allocationMode left right
|> ClVector.Dense
|> Some
| _ -> failwith "Vector formats are not matching."
/// <summary>
/// Applying the given function to the corresponding elements of the two given arrays pairwise.
/// Stores the result in the left vector.
/// </summary>
/// <remarks>
/// The two input arrays must have the same lengths.
/// </remarks>
/// <param name="map">The function to transform the pairs of the input elements.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2InPlace (map: Expr<'a option -> 'b option -> 'a option>) (clContext: ClContext) workGroupSize =
let map2Dense =
Dense.Vector.map2InPlace map clContext workGroupSize
fun (processor: RawCommandQueue) (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) ->
match leftVector, rightVector with
| ClVector.Dense left, ClVector.Dense right -> map2Dense processor left right left
| _ -> failwith "Unsupported vector format"
/// <summary>
/// Applying the given function to the corresponding elements of the two given arrays pairwise.
/// Stores the result in the given vector.
/// </summary>
/// <remarks>
/// The two input arrays must have the same lengths.
/// </remarks>
/// <param name="map">The function to transform the pairs of the input elements.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2To (map: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize =
let map2Dense =
Dense.Vector.map2InPlace map clContext workGroupSize
fun (processor: RawCommandQueue) (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) (resultVector: ClVector<'c>) ->
match leftVector, rightVector, resultVector with
| ClVector.Dense left, ClVector.Dense right, ClVector.Dense result ->
map2Dense processor left right result
| _ -> failwith "Unsupported vector format"
/// <summary>
/// Applying the given function to the corresponding elements of the two given arrays pairwise.
/// Returns new vector.
/// </summary>
/// <remarks>
/// The two input arrays must have the same lengths.
/// </remarks>
/// <param name="map">The function to transform the pairs of the input elements.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2Dense (map: Expr<'a option -> 'b option -> 'a option>) (clContext: ClContext) workGroupSize =
let map2Dense =
Dense.Vector.map2 map clContext workGroupSize
fun (processor: RawCommandQueue) allocationFlag (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) ->
match leftVector, rightVector with
| ClVector.Dense left, ClVector.Dense right -> map2Dense processor allocationFlag left right
| _ -> failwith "Unsupported vector format"
/// <summary>
/// Applying the given function to the corresponding elements of the two given arrays pairwise.
/// Returns new vector as option.
/// </summary>
/// <remarks>
/// The two input arrays must have the same lengths.
/// </remarks>
/// <param name="map">The function to transform the pairs of the input elements.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2Sparse (map: Expr<'a option -> 'b option -> 'a option>) (clContext: ClContext) workGroupSize =
let map2Sparse =
Sparse.Map2.run map clContext workGroupSize
let map2SparseDense =
Sparse.Map2.runSparseDense map clContext workGroupSize
fun (processor: RawCommandQueue) allocationFlag (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) ->
match leftVector, rightVector with
| ClVector.Sparse left, ClVector.Sparse right ->
Option.map ClVector.Sparse (map2Sparse processor allocationFlag left right)
| ClVector.Sparse left, ClVector.Dense right ->
Option.map ClVector.Sparse (map2SparseDense processor allocationFlag left right)
| _ -> failwith "Unsupported vector format"
module Matrix =
/// <summary>
/// Builds a new matrix whose elements are the results of applying the given function
/// to each of the elements of the matrix.
/// </summary>
/// <param name="op">
/// A function to transform values of the input matrix.
/// Operand and result types should be optional to distinguish explicit and implicit zeroes
/// </param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map (op: Expr<'a option -> 'b option>) (clContext: ClContext) workGroupSize =
let mapCOO =
COO.Matrix.map op clContext workGroupSize
let mapCSR =
CSR.Matrix.map op clContext workGroupSize
let transposeCOO =
COO.Matrix.transposeInPlace clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode matrix ->
match matrix with
| ClMatrix.COO m -> mapCOO processor allocationMode m |> ClMatrix.COO
| ClMatrix.CSR m -> mapCSR processor allocationMode m |> ClMatrix.COO
| ClMatrix.CSC m ->
(mapCSR processor allocationMode m.ToCSR)
|> transposeCOO processor
|> ClMatrix.COO
| _ -> failwith "Not yet implemented"
/// <summary>
/// Builds a new matrix whose values are the results of applying the given function
/// to the corresponding pairs of values from the two matrices.
/// </summary>
/// <param name="op">
/// A function to transform pairs of values from the input matrices.
/// Operands and result types should be optional to distinguish explicit and implicit zeroes
/// </param>
/// <remarks>
/// Formats of the given matrices should match, otherwise an exception will be thrown.
/// </remarks>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2 (op: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize =
let map2COO =
COO.Matrix.map2 op clContext workGroupSize
let map2CSR =
CSR.Matrix.map2 op clContext workGroupSize
let transposeCOO =
COO.Matrix.transposeInPlace clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode matrix1 matrix2 ->
match matrix1, matrix2 with
| ClMatrix.COO m1, ClMatrix.COO m2 ->
map2COO processor allocationMode m1 m2
|> ClMatrix.COO
| ClMatrix.CSR m1, ClMatrix.CSR m2 ->
map2CSR processor allocationMode m1 m2
|> ClMatrix.COO
| ClMatrix.CSC m1, ClMatrix.CSC m2 ->
(map2CSR processor allocationMode m1.ToCSR m2.ToCSR)
|> transposeCOO processor
|> ClMatrix.COO
| _ -> failwith "Matrix formats are not matching"
/// <summary>
/// Builds a new matrix whose values are the results of applying the given function
/// to the corresponding pairs of values from the two matrices.
/// </summary>
/// <param name="op">
/// A function to transform pairs of values from the input matrices.
/// Operation assumption: one of the operands should always be non-zero.
/// </param>
/// <remarks>
/// Formats of the given matrices should match, otherwise an exception will be thrown.
/// </remarks>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let map2AtLeastOne (op: Expr<AtLeastOne<'a, 'b> -> 'c option>) (clContext: ClContext) workGroupSize =
let COOMap2 =
COO.Matrix.map2AtLeastOne clContext op workGroupSize
let CSRMap2 =
CSR.Matrix.map2AtLeastOne clContext op workGroupSize
let COOTranspose =
COO.Matrix.transposeInPlace clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode matrix1 matrix2 ->
match matrix1, matrix2 with
| ClMatrix.COO m1, ClMatrix.COO m2 ->
COOMap2 processor allocationMode m1 m2
|> ClMatrix.COO
| ClMatrix.CSR m1, ClMatrix.CSR m2 ->
CSRMap2 processor allocationMode m1 m2
|> ClMatrix.COO
| ClMatrix.CSC m1, ClMatrix.CSC m2 ->
(CSRMap2 processor allocationMode m1.ToCSR m2.ToCSR)
|> COOTranspose processor
|> ClMatrix.COO
| _ -> failwith "Matrix formats are not matching"
/// <summary>
/// Matrix-vector multiplication.
/// Vector, that is going to be the result of the operation, should be passed as an argument.
/// </summary>
/// <param name="add">Type of binary function to reduce entries.</param>
/// <param name="mul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let SpMVInPlace
(add: Expr<'c option -> 'c option -> 'c option>)
(mul: Expr<'a option -> 'b option -> 'c option>)
(clContext: ClContext)
workGroupSize
=
let runTo =
SpMV.runTo add mul clContext workGroupSize
fun (queue: RawCommandQueue) (matrix: ClMatrix<'a>) (vector: ClVector<'b>) (result: ClVector<'c>) ->
match matrix, vector, result with
| ClMatrix.CSR m, ClVector.Dense v, ClVector.Dense r -> runTo queue m v r
| _ -> failwith "Not implemented yet"
/// <summary>
/// CSR Matrix - dense vector multiplication.
/// </summary>
/// <param name="add">Type of binary function to reduce entries.</param>
/// <param name="mul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let SpMV
(add: Expr<'c option -> 'c option -> 'c option>)
(mul: Expr<'a option -> 'b option -> 'c option>)
(clContext: ClContext)
workGroupSize
=
let run = SpMV.run add mul clContext workGroupSize
fun (queue: RawCommandQueue) allocationFlag (matrix: ClMatrix<'a>) (vector: ClVector<'b>) ->
match matrix, vector with
| ClMatrix.CSR m, ClVector.Dense v -> run queue allocationFlag m v |> ClVector.Dense
| _ -> failwith "Not implemented yet"
/// <summary>
/// CSR Matrix - sparse vector multiplication. Optimized for bool OR and AND operations by skipping reduction stage.
/// </summary>
/// <param name="add">Type of binary function to reduce entries.</param>
/// <param name="mul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let SpMSpVBool
(add: Expr<bool option -> bool option -> bool option>)
(mul: Expr<bool option -> bool option -> bool option>)
(clContext: ClContext)
workGroupSize
=
let run =
SpMSpV.runBoolStandard add mul clContext workGroupSize
fun (queue: RawCommandQueue) (matrix: ClMatrix<bool>) (vector: ClVector<bool>) ->
match matrix, vector with
| ClMatrix.CSR m, ClVector.Sparse v -> Option.map ClVector.Sparse (run queue m v)
| _ -> failwith "Not implemented yet"
/// <summary>
/// CSR Matrix - sparse vector multiplication with mask. Mask is complemented.
/// </summary>
/// <param name="add">Type of binary function to reduce entries.</param>
/// <param name="mul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let SpMSpVMasked
(add: Expr<'c option -> 'c option -> 'c option>)
(mul: Expr<'a option -> 'b option -> 'c option>)
(clContext: ClContext)
workGroupSize
=
let run =
SpMSpV.Masked.runMasked add mul clContext workGroupSize
fun (queue: RawCommandQueue) (matrix: ClMatrix<'a>) (vector: ClVector<'b>) (mask: ClVector<'d>) ->
match matrix, vector, mask with
| ClMatrix.CSR m, ClVector.Sparse v, ClVector.Dense mask -> Option.map ClVector.Sparse (run queue m v mask)
| _ -> failwith "Not implemented yet"
/// <summary>
/// CSR Matrix - sparse vector multiplication with mask. Mask is complemented. Optimized for bool OR and AND operations by skipping reduction stage.
/// </summary>
/// <param name="add">Type of binary function to reduce entries.</param>
/// <param name="mul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let SpMSpVMaskedBool
(add: Expr<bool option -> bool option -> bool option>)
(mul: Expr<bool option -> bool option -> bool option>)
(clContext: ClContext)
workGroupSize
=
let run =
SpMSpV.Masked.runMaskedBoolStandard add mul clContext workGroupSize
fun (queue: RawCommandQueue) (matrix: ClMatrix<'a>) (vector: ClVector<'b>) (mask: ClVector<'d>) ->
match matrix, vector, mask with
| ClMatrix.CSR m, ClVector.Sparse v, ClVector.Dense mask -> Option.map ClVector.Sparse (run queue m v mask)
| _ -> failwith "Not implemented yet"
/// <summary>
/// CSR Matrix - sparse vector multiplication.
/// </summary>
/// <param name="add">Type of binary function to reduce entries.</param>
/// <param name="mul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let SpMSpV
(add: Expr<'c option -> 'c option -> 'c option>)
(mul: Expr<'a option -> 'b option -> 'c option>)
(clContext: ClContext)
workGroupSize
=
let run =
SpMSpV.run add mul clContext workGroupSize
fun (queue: RawCommandQueue) (matrix: ClMatrix<'a>) (vector: ClVector<'b>) ->
match matrix, vector with
| ClMatrix.CSR m, ClVector.Sparse v -> Option.map ClVector.Sparse (run queue m v)
| _ -> failwith "Not implemented yet"
/// <summary>
/// Kronecker product for matrices.
/// </summary>
/// <param name="op">
/// Element-wise operation.
/// Operands and result types should be optional to distinguish explicit and implicit zeroes
/// </param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let kronecker (op: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize =
let run = Kronecker.run clContext workGroupSize op
fun (queue: RawCommandQueue) allocationFlag (matrix1: ClMatrix<'a>) (matrix2: ClMatrix<'b>) ->
match matrix1, matrix2 with
| ClMatrix.CSR m1, ClMatrix.CSR m2 ->
let result = run queue allocationFlag m1 m2
Option.map ClMatrix.COO result
| _ -> failwith "Both matrices should be in CSR format."
/// <summary>
/// Sparse general matrix-matrix multiplication.
/// </summary>
module SpGeMM =
/// <summary>
/// Masked matrix-matrix multiplication.
/// </summary>
/// <param name="opAdd">Type of binary function to reduce entries.</param>
/// <param name="opMul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let masked
(opAdd: Expr<'c -> 'c -> 'c option>)
(opMul: Expr<'a -> 'b -> 'c option>)
(clContext: ClContext)
workGroupSize
=
let runCSRnCSC =
SpGeMM.Masked.run opAdd opMul clContext workGroupSize
fun (queue: RawCommandQueue) (matrix1: ClMatrix<'a>) (matrix2: ClMatrix<'b>) (mask: ClMatrix<_>) ->
match matrix1, matrix2, mask with
| ClMatrix.CSR m1, ClMatrix.CSC m2, ClMatrix.COO mask -> runCSRnCSC queue m1 m2 mask |> ClMatrix.COO
| _ -> failwith "Matrix formats are not matching"
/// <summary>
/// Generalized matrix-matrix multiplication.
/// </summary>
/// <param name="opAdd">Type of binary function to reduce entries.</param>
/// <param name="opMul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let expand
(opAdd: Expr<'c -> 'c -> 'c option>)
(opMul: Expr<'a -> 'b -> 'c option>)
(clContext: ClContext)
workGroupSize
=
let run =
SpGeMM.Expand.run opAdd opMul clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) ->
match leftMatrix, rightMatrix with
| ClMatrix.CSR leftMatrix, ClMatrix.CSR rightMatrix ->
let allocCapacity =
List.max [ sizeof<'a>
sizeof<'c>
sizeof<'b> ]
|> uint64
|> (*) 1UL<Byte>
let resultCapacity =
(clContext.MaxMemAllocSize / allocCapacity) / 3UL
let resultCapacity =
(min
<| uint64 System.Int32.MaxValue
<| resultCapacity)
|> int
run processor allocationMode resultCapacity leftMatrix rightMatrix
| _ -> failwith "Matrix formats are not matching"
module COO =
/// <summary>
/// Generalized matrix-matrix multiplication. Left matrix should be in COO format.
/// </summary>
/// <param name="opAdd">Type of binary function to reduce entries.</param>
/// <param name="opMul">Type of binary function to combine entries.</param>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let expand
(opAdd: Expr<'c -> 'c -> 'c option>)
(opMul: Expr<'a -> 'b -> 'c option>)
(clContext: ClContext)
workGroupSize
=
let run =
SpGeMM.Expand.COO.run opAdd opMul clContext workGroupSize
fun (processor: RawCommandQueue) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) ->
match leftMatrix, rightMatrix with
| ClMatrix.COO leftMatrix, ClMatrix.CSR rightMatrix ->
let allocCapacity =
List.max [ sizeof<'a>
sizeof<'c>
sizeof<'b> ]
|> uint64
|> (*) 1UL<Byte>
let resultCapacity =
(clContext.MaxMemAllocSize / allocCapacity) / 3UL
let resultCapacity =
(min
<| uint64 System.Int32.MaxValue
<| resultCapacity)
|> int
run processor allocationMode resultCapacity leftMatrix rightMatrix
| _ -> failwith "Matrix formats are not matching"