Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add support for GAP8 hardware convolution engine #197

Open
wants to merge 92 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
07d7cab
Added convolution imperative primitives for GAP8
bpervan Jul 23, 2021
03ba5fd
Swapped dimensions of the input and output arrays
bpervan Jul 26, 2021
b4f75c2
Added RISE HWCE primitives
bpervan Jul 29, 2021
e86e2a4
Added functional primitives for HWCE
bpervan Jul 29, 2021
cd7dcb7
Parts of translation implementation for GAP8 HWCE
bpervan Jul 29, 2021
8bbc51b
Added HWCE test prototype
bpervan Jul 29, 2021
10abc44
GAP8 hwce tests + minor code cleanup
bpervan Aug 18, 2021
b767fb1
WIP: GAP8 hwce primitives
bpervan Aug 18, 2021
2c1bdc0
WIP: GAP8 hwce rise primitives
bpervan Aug 18, 2021
dafa91e
WIP: GAP8 hwce translation implementation
bpervan Aug 18, 2021
885d269
Merge branch 'main' into gap8-hwce
bpervan Aug 18, 2021
a279122
Merge branch 'main' into gap8-hwce
bpervan Sep 6, 2021
5d3b4d6
Updated gap8hwConv primitive
bpervan Sep 8, 2021
ae2da4b
Updated translation chain regarding gap8 hwce
bpervan Sep 8, 2021
968a181
Updated DataType(s) in gap8 hwce test
bpervan Sep 8, 2021
6a9b942
Temporary ignoring hwce tests
bpervan Sep 8, 2021
64759a3
WIP: HWCE code generation debugging
bpervan Sep 10, 2021
b843fc2
Tests HWCE
bpervan Sep 10, 2021
4579ef6
Not fix for minimal hwce example
michel-steuwer Sep 10, 2021
0bc3aea
Merge branch 'main' into gap8-hwce
bpervan Sep 20, 2021
46fbf5d
Added rest of the conv primitives
bpervan Sep 21, 2021
afe8a98
Added rest of the DPIA primitives regarding gap8 hwce
bpervan Sep 21, 2021
2907da9
Ignoring currently unfunctional test
bpervan Sep 21, 2021
238a8fe
Minor cleanup
bpervan Sep 21, 2021
1951cb5
Added HWCE call check, tests should invoke generation of the Hosted M…
bpervan Oct 20, 2021
3e400da
Added implementatinos for other types of convolution
bpervan Oct 20, 2021
bd81b63
Slightly refactored tests in codegen, added kmeans test
bpervan Oct 20, 2021
1941090
Working on HWCE support; Bugfixes regarding code generation for GAP8 …
bpervan Oct 20, 2021
9a611b6
Merge branch 'main' into gap8-hwce; Added import for GAP8 primitives
bpervan Oct 20, 2021
577a678
Added GAP8 hardware convolution rule
bpervan Oct 23, 2021
13ce0e9
Fixed HWCE strategy
bpervan Oct 25, 2021
075a164
Added test cases to hwce test suite
bpervan Oct 25, 2021
b72ae8e
Flipped output matrix dimensions
bpervan Oct 25, 2021
554cd43
Added rest of the HWCE primitives; Minor refactor
bpervan Oct 25, 2021
a5cf5f3
Added support for HWCE primitives (other than 3x3); Minor refactor
bpervan Oct 25, 2021
24defe8
hwce tests ignore -> test
bpervan Oct 25, 2021
afb1e20
mapSeq -> mapPar; Removed transpose from KMeans test
bpervan Oct 29, 2021
5a2b2ac
Added sobel filter + hwce test (currently ignored)
bpervan Oct 29, 2021
7e29211
Added convolution 3x3 test
bpervan Oct 29, 2021
b3afce4
Minor test refactors
bpervan Oct 29, 2021
1e631ba
Merge branch 'main' into gap8-hwce
bpervan Oct 29, 2021
494aaaa
C/P #218
bpervan Oct 29, 2021
2e031c5
Merge branch 'main' into gap8-hwce
bpervan May 16, 2022
de1247b
Minor cleanup
bpervan Jun 8, 2022
e6119f0
Uncommented syntax checking step for gap8 function generation; Commen…
bpervan Jul 12, 2022
54d6cbc
Added comment hinting future syntax checking of GAP8 code
bpervan Jul 12, 2022
b573b3e
Added DMA transfer-supporting primitives for GAP8
bpervan Apr 25, 2023
43754cd
GAP8 DMA support helper classes and constructs
bpervan Apr 25, 2023
c696bc0
WIP: Code generator for memory allocation and DMA transfers on GAP8 a…
bpervan Apr 25, 2023
7ea37bc
GAP8 copyToL1 and copyToL2 translation implementation
bpervan Apr 25, 2023
4563119
WIP: copyToL1 and copyToL2 support for GAP8
bpervan Apr 25, 2023
66d2269
Added temp application for implementation testing (GAP8 DMA and HWCE)
bpervan Apr 25, 2023
f4fe99f
Changed access annotation from read to write for src in dmaCopy; Cleanup
bpervan Apr 26, 2023
9640b63
Refactor & cleanup
bpervan Apr 26, 2023
5a75ce0
Changed memory allocation / dma transfer paradigm
bpervan Apr 27, 2023
84bf589
Added alloc consts to MemoryType; Added brief implementation of type …
bpervan Apr 27, 2023
21e5f09
Malloc / DMA transfer refactor
bpervan Apr 27, 2023
7c7b9e1
WIP: Implementation of code generation for Malloc / DMA transfer
bpervan Apr 27, 2023
c4ea399
Minor refactor
bpervan Apr 28, 2023
b8423cd
Added GAP8 + HWCE + DMA testing application
bpervan May 4, 2023
4ee9277
Temporary debugging println; Added (commented) alternative Phrase for…
bpervan May 4, 2023
bd38ac4
Temporary debugging printlns
bpervan May 4, 2023
951e939
Added Cast primitive; Added pattern matching case to ContinuationTran…
bpervan May 5, 2023
311e786
Removed swapEnvIdentifier as it's no longer necessary; Added appropri…
bpervan May 5, 2023
8e519db
Added event set call to GAP8 module
bpervan May 15, 2023
ecb0441
Pointer cast when generating rt_alloc call; Array declaration is now …
bpervan May 15, 2023
27ec7c4
Added toStdint method
bpervan May 15, 2023
b65766e
Handled ext/loc memory references in the context of DMA transfers
bpervan May 15, 2023
db29ccc
DMA + 2xHWCE WIP
bpervan May 18, 2023
3e08918
Fixed bug with updateRanges
michel-steuwer May 18, 2023
a1c2764
Changed (fixed) HWCE primitives to conform to row-first 2D array model
bpervan May 19, 2023
7d70016
Dma / Hwce / Tiling WIP
bpervan May 19, 2023
a2e0de4
Added GAP8-specific part of the syntax checking pipeline (fixes synta…
bpervan May 22, 2023
4b1d0c6
WIP: Slide() debug, added more examples
bpervan May 23, 2023
8a05f1e
Adding CIntExpr(0) to path when calling acc / exp (DmaCopy codegen)
bpervan May 26, 2023
1455d3e
WIP
bpervan Jun 1, 2023
6d67bc7
WIP; Comment
bpervan Jun 12, 2023
12ecfc1
copy2DOffsetToL1 primitive
bpervan Jun 12, 2023
1f283d5
copy2DOffsetToL1 translation
bpervan Jun 12, 2023
bf5407c
WIP tiledFixSizeDmaHwce app
bpervan Jun 12, 2023
3600b73
Added dma2DOffsetCopy and memorySet primitives.
michel-steuwer Jun 13, 2023
7e49f4d
Refactored GAP8 primitives to make them uniform with other primitives…
bpervan Jun 16, 2023
929b38f
Primitives interface refactor (for conv primitives); MemorySet and Dm…
bpervan Jun 16, 2023
57f911b
Dma2DOffsetCopy codegen implementation
bpervan Jun 17, 2023
50b3ce2
Added ampersand unary op and cast to dma transfers; Added (incomplete…
bpervan Jul 4, 2023
1e83ce6
WIP: HwceDma apps
bpervan Jul 4, 2023
9257bb6
Added collapse rule proto
bpervan Oct 22, 2023
67200e1
Added DMA-HWCE expressions; Added tester file (to be removed probably…
bpervan Oct 22, 2023
e2a899e
2D Loop transfer codegen (proto, unfinished)
bpervan Oct 22, 2023
5cd93e9
Added Sobel without pad
Oct 24, 2023
880db25
Added SobelWithoutPadHWCE, slightly changed SobelWithoutPad
bpervan Oct 24, 2023
acd3491
tester cleanup; GAP8HwceDma added Gaussian blur variants (plain, HWCE…
bpervan Oct 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
373 changes: 373 additions & 0 deletions src/main/scala/apps/GAP8HwceDma.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,373 @@
package apps

import arithexpr.arithmetic.NamedVar
import elevate.core.Strategy
import rise.GAP8.DSL.gap8Run
import rise.GAP8.primitives.{allocL1, allocL2, copy2DOffsetToL1, copyToL1, copyToL2, gap8hwConv3x3, gap8hwConv5x5}
import rise.core.DSL.HighLevelConstructs.{padCst2D, slide2D, zipND}
import rise.core.DSL.Type.TypeConstructors
import rise.core.DSL.{ToBeTyped, depFun, foreignFun, fun, letf, li16}
import rise.core.primitives._
import rise.core.types.DataType.{ArrayType, i16, int, u8}
import rise.core.types.Nat
import rise.elevate.Rise
import rise.elevate.strategies.traversal.everywhere
import rise.elevate.strategies.traversal.AtHelper
import rise.elevate.rules.lowering.`map -> mapPar`
import rise.openMP.primitives.mapPar
import shine.GAP8.Module.translateToString

// scalastyle: off
object GAP8HwceDma {
def main(args: Array[String]): Unit = {
//24.10.2023. If Type is i16 -> i16, one should be 1u << 14
val gapSqrt = foreignFun("gap_sqrt",
Seq("a_nInput"),
"""
| {
| uint32_t op = a_nInput;
| uint32_t res = 0;
|
| uint32_t one = 1uL << 30;
| while (one > op){
| one >>= 2;
| }
| while (one != 0) {
| if (op >= res + one){
| op = op - (res + one);
| res = res + 2 * one;
| }
| res >>= 1;
| one >>= 2;
| }
| return res;
| }
|""".stripMargin,
i16 ->: i16
)

val size: Nat = 4
val fixSize: ToBeTyped[Rise] = fun(ArrayType(size, u8) ->: ArrayType(size, u8))(in =>
gap8Run(8)(
in |>
copyToL1 |>
allocL1 |>
mapSeq(fun(x => x)) |>
allocL1 |>
copyToL2
)
)
//println(translateToString(util.gen.gap8.hosted.fromExpr(fixSize)))

val varSize: ToBeTyped[Rise] = depFun((sz: Nat) =>
fun(ArrayType(sz, u8) ->: ArrayType(sz, u8))(in =>
gap8Run(8)(
in |>
copyToL1 |>
allocL1 |>
mapSeq(fun(x => x)) |>
allocL1 |>
copyToL2
)))
//println(translateToString(util.gen.gap8.hosted.fromExpr(varSize)))

val fixSizeDmaHwce: ToBeTyped[Rise] = fun(
ArrayType(size, ArrayType(size, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(size - 2, ArrayType(size - 2, i16)))((in, filter) =>
gap8Run(8)(
in |> copyToL1 |> allocL1 |> letf(innerin =>
filter |> copyToL1 |> allocL1 |> letf(innerf =>
gap8hwConv3x3(0)(innerin, innerf) |> allocL1 |> copyToL2
)
)
)
)
//println(translateToString(util.gen.gap8.hosted("conv").fromExpr(fixSizeDmaHwce)))

//Passes
val theSmallestSlide: ToBeTyped[Rise] = fun(
ArrayType(5, i16) ->: ArrayType(3, ArrayType(3, i16))
)(arr =>
gap8Run(8)(
arr |> slide(3)(1) |> mapSeq(mapSeq(fun(elem => add(elem)(li16(1)))))
)
)
//printf(translateToString(util.gen.gap8.hosted("theSmallest").fromExpr(theSmallestSlide)))
//translateToString(util.gen.gap8.hosted("theSmallest").fromExpr(theSmallestSlide))
println("======================================================================")

val inBetweenSlideExample: ToBeTyped[Rise] = fun(
ArrayType(5, i16) ->: ArrayType(3, ArrayType(3, i16))
)(arr =>
gap8Run(8)(
arr |> slide(3)(1) |> mapSeq(fun(tile =>
tile |> copyToL1 |> allocL1 |> letf(tstletf =>
tstletf |> mapSeq(fun(elem => add(elem)(li16(1)))) |> allocL1 |> copyToL2
)
))
)
)
//println(translateToString(util.gen.gap8.hosted("inBetween").fromExpr(inBetweenSlideExample)))
//translateToString(util.gen.gap8.hosted("inBetween").fromExpr(inBetweenSlideExample))
println("======================================================================")

//Does not pass
val thisMaybe: ToBeTyped[Rise] = fun(
ArrayType(5, i16) ->: ArrayType(9, i16)
)(arr =>
gap8Run(8)(
arr |> slide(3)(1) |> join |> copyToL1 |> allocL1 |> letf(sth =>
sth |> mapSeq(fun(elem => add(elem)(li16(1)))) |> allocL1 |> copyToL2
)
)
)
//println(translateToString(util.gen.gap8.hosted("thisMaybe").fromExpr(thisMaybe)))
//translateToString(util.gen.gap8.hosted("thisMaybe").fromExpr(thisMaybe))

//Does not pass either
val evenSmallerSlideExample: ToBeTyped[Rise] = fun(
ArrayType(5, i16) ->: ArrayType(3, ArrayType(3, i16))
)(arr =>
gap8Run(8)(
arr |> slide(3)(1) |> mapSeq(fun(tile =>
tile |> copyToL1 |> allocL1 |> letf(tilel1 =>
tilel1 |> mapSeq(fun(elem => add(elem)(li16(1)))) |> allocL1 |> copyToL2
)
))
)
)
//println(translateToString(util.gen.gap8.hosted("evenSmallerSlideExample").fromExpr(evenSmallerSlideExample)))
//translateToString(util.gen.gap8.hosted("evenSmallerSlideExample").fromExpr(evenSmallerSlideExample))

//No way
val minSlideExample: ToBeTyped[Rise] = fun(
ArrayType(5, ArrayType(5, i16)) ->:
ArrayType(3, ArrayType(5, i16)) ->:
ArrayType(9, ArrayType(5, i16)))((sth, filter) =>
gap8Run(8)(
sth |> slide(3)(1) |> mapSeq(fun(tile =>
tile |> copyToL1 |> allocL1 |> letf(tilel1 =>
zipND(2)(tilel1, filter) |> mapPar(mapPar(fun(elems =>
add(fst(elems))(snd(elems))
))) |> allocL1 |> copyToL2
)
)) |> join
)
)
//println(translateToString(util.gen.gap8.hosted("minSlide").fromExpr(minSlideExample)))

val w: Nat = 320
val h: Nat = 240
//Padded horizontally
val tiledFixSizeDmaHwce: ToBeTyped[Rise] =
fun(
ArrayType(h, ArrayType(w, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(h - 2, ArrayType(w, i16)))((pic, hw, vw) =>
gap8Run(8)(
hw |> copyToL1 |> allocL1 |> letf(l1hw =>
vw |> copyToL1 |> allocL1 |> letf(l1vw =>
// pic |> padCst2D(1, 1, 0, 0)(li16(0)) |> slide(16)(14) |>
// pic: 240.320.i16
pic |> slide (16)(14) |>
// 14*16+16 => 240 (n: 16)
// 17.16.320.i16
mapSeq(fun(stripe =>
// stripe: 16.320.i16
stripe |> copy2DOffsetToL1(0)(1) |> allocL1 |> // letf(l1stripe =>

// l1stripe |> padCst2D(0, 0, 1, 1)(li16(0)) |>
// mapSeq(mapSeq(fun(x => x))) |> allocL1 |>
// l1convstripe: 18.322.i16
// if offsetH = 0 -> 16.322.i16
letf(l1convstripe =>
// convresult(s): 16.320.i16
// if offsetH =0 -> 14.320.i16
gap8hwConv3x3(0)(l1convstripe, l1hw) |> allocL1 |> letf(hconvres =>
gap8hwConv3x3(0)(l1convstripe, l1vw) |> allocL1 |> letf(vconvres =>
// zipND: 16.320.(i16, i16)
zipND(2)(hconvres)(vconvres) |> mapPar(mapPar(fun(elems =>
gapSqrt(add(mul(fst(elems))(fst(elems)))(mul(snd(elems))(snd(elems))))
//copy back 16.320.i16
))) |> allocL1 |> copyToL2
)
)
// )
)
//(17*16).320.i16
//offsetH -> 0 (17*14).320.i16
)) |> join
)
)
)
)
//println(translateToString(util.gen.gap8.hosted("tiledConv").fromExpr(tiledFixSizeDmaHwce)))

//Padded vertically
val tiledFixSizeDmaHwcePaddedVertically: ToBeTyped[Rise] =
fun(
ArrayType(h, ArrayType(w, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(h - 2, ArrayType(w - 2, i16)))((pic, hw, vw) =>
gap8Run(8)(
hw |> copyToL1 |> allocL1 |> letf(l1hw =>
vw |> copyToL1 |> allocL1 |> letf(l1vw =>
// pic: 240.320.i16
pic |> slide(16)(14) |>
// 14*16+16 => 240 (n: 16)
// 17.16.320.i16
mapSeq(fun(stripe =>
// stripe: 16.320.i16
stripe |> copy2DOffsetToL1(1)(0) |> allocL1 |> // letf(l1stripe =>
// l1convstripe 18.320.i16
letf(l1convstripe =>
// convresult(s): 16.318.i16
gap8hwConv3x3(0)(l1convstripe, l1hw) |> allocL1 |> letf(hconvres =>
gap8hwConv3x3(0)(l1convstripe, l1vw) |> allocL1 |> letf(vconvres =>
// zipND: 16.318.(i16, i16)
zipND(2)(hconvres)(vconvres) |> mapPar(mapPar(fun(elems =>
gapSqrt(add(mul(fst(elems))(fst(elems)))(mul(snd(elems))(snd(elems))))
//copy back 16.318.i16
))) |> allocL1 |> take(15) |> drop(1) |> copyToL2
)
)
)
//(17*16).318.i16
)) |> join
)
)
)
)
//println(translateToString(util.gen.gap8.hosted("tiledConv").fromExpr(tiledFixSizeDmaHwcePaddedVertically)))

val tiledFixSizeDmaHwceNoPadding: ToBeTyped[Rise] =
fun(
ArrayType(h, ArrayType(w, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(h - 2, ArrayType(w - 2, i16)))((pic, hw, vw) =>
gap8Run(8)(
hw |> copyToL1 |> allocL1 |> letf(l1hw =>
vw |> copyToL1 |> allocL1 |> letf(l1vw =>
// pic: 240.320.i16
pic |> slide(16)(14) |>
// 14*16+16 => 240 (n: 16)
// 17.16.320.i16
mapSeq(fun(stripe =>
// stripe: 16.320.i16
stripe |> copyToL1 |> allocL1 |> // letf(l1stripe =>
// l1convstripe 16.320.i16
letf(l1convstripe =>
// convresult(s): 14.318.i16
gap8hwConv3x3(0)(l1convstripe, l1hw) |> allocL1 |> letf(hconvres =>
gap8hwConv3x3(0)(l1convstripe, l1vw) |> allocL1 |> letf(vconvres =>
// zipND: 14.318.(i16, i16)
zipND(2)(hconvres)(vconvres) |> mapPar(mapPar(fun(elems =>
gapSqrt(add(mul(fst(elems))(fst(elems)))(mul(snd(elems))(snd(elems))))
//copy back 14.318.i16
))) |> allocL1 |> copyToL2
)
)
)
//

)) |> join
)
)
)
)
//println(translateToString(util.gen.gap8.hosted("tiledConv").fromExpr(tiledFixSizeDmaHwceNoPadding)))
val ww: Nat = 320
val hh: Nat = 244
val tiledFixSizeDmaHwceNoPadding_Gaussian: ToBeTyped[Rise] =
fun(
ArrayType(hh, ArrayType(ww, i16)) ->:
ArrayType(5, ArrayType(5, i16)) ->:
ArrayType(hh - 4, ArrayType(ww - 4, i16)))((pic, filter) =>
gap8Run(8)(
filter |> copyToL1 |> allocL1 |> letf(l1filter =>
// pic: 240.320.i16
pic |> slide(16)(12) |>
// step * n + size = 240
// 17.16.320.i16
mapSeq(fun(stripe =>
//stripe 16.320.i16
stripe |> copyToL1 |> allocL1 |>
letf(l1stripe =>
// convresult (12.316.i16)
gap8hwConv5x5(0)(l1stripe, l1filter) |> allocL1 |> copyToL2
)
)) |> join
)
)
)
println(translateToString(util.gen.gap8.hosted("GaussianBlur").fromExpr(tiledFixSizeDmaHwceNoPadding_Gaussian)))

val gaussianNoPadHWCE: ToBeTyped[Rise] = fun(
ArrayType(hh, ArrayType(ww, i16)) ->:
ArrayType(5, ArrayType(5, i16)) ->:
ArrayType(hh - 4, ArrayType(ww - 4, i16))
)((pic, filter) =>
gap8Run(8)(
gap8hwConv5x5(0)(pic, filter)
)
)
println(translateToString(util.gen.gap8.hosted("GaussianBlur_HWCE").fromExpr(gaussianNoPadHWCE)))

val gaussianBlurPlain: ToBeTyped[Rise] = fun(
ArrayType(hh, ArrayType(ww, i16)) ->:
ArrayType(5, ArrayType(5, i16)) ->:
ArrayType(hh - 4, ArrayType(ww - 4, i16))
)((pic, filter) =>
gap8Run(8)(
pic |>
slide2D(sz = 5, st = 1) |>
mapPar(mapPar(fun(submat =>
zip(submat |> join)(filter |> join) |> map(fun(e => fst(e) * snd(e))) |> reduceSeqUnroll(add)(li16(0))
)))
)
)
println(translateToString(util.gen.gap8.hosted("GaussianBlur_Plain").fromExpr(gaussianBlurPlain)))

/*val strategy: Strategy[Rise] =
`map -> mapPar` `@` everywhere
val ex_mapfor: ToBeTyped[Rise] = depFun((n: Nat) =>
fun(ArrayType(n, int) ->: ArrayType(n, int))(input =>
input |> map(fun(x => x))
)
)
println(util.gen.openmp.function("ex_mapfor").asStringFromExpr(strategy(ex_mapfor).get))*/

val simpleNoSlide: ToBeTyped[Rise] =
fun(
ArrayType(size, ArrayType(size, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(3, ArrayType(3, i16)) ->:
ArrayType(size - 2, ArrayType(size - 2, i16)))((pic, hw, vw) =>
gap8Run(8)(
hw |> copyToL1 |> allocL1 |> letf(l1hw =>
vw |> copyToL1 |> allocL1 |> letf(l1vw =>
pic |> copyToL1 |> allocL1 |> letf(l1pic =>
gap8hwConv3x3(0)(l1pic, l1hw) |> allocL1 |> letf (hconvres => // hconvres |> copyToL2
gap8hwConv3x3(0)(l1pic, l1vw) |> allocL1 |> letf (vconvres =>
zipND(2)(hconvres)(vconvres) |> mapPar(mapPar(fun(elems =>
add(fst(elems))(snd(elems))
))) |> allocL1 |> copyToL2
/*zip(hconvres)(vconvres) |> mapPar(fun(rows =>
zip(fst(rows))(snd(rows)) |> mapPar(fun(elems =>
add(fst(elems))(snd(elems))
))
)) |> allocL1 |> copyToL2*/
)
)
)
)
)
)
)
//println(translateToString(util.gen.gap8.hosted("doubleconv").fromExpr(simpleNoSlide)))
}
}
Loading
Loading