From 961c68ec612745bc925d076fcd9710020e47954d Mon Sep 17 00:00:00 2001 From: shas19 Date: Fri, 31 Jul 2020 11:55:35 +0530 Subject: [PATCH] All the changes for resnet --- Tools/SeeDot/SeeDot-dev.py | 16 +- .../SeeDot/seedot/Predictor/library_fixed.cpp | 168 ++++++++++-- Tools/SeeDot/seedot/Predictor/library_fixed.h | 186 +++++++++++-- .../SeeDot/seedot/Predictor/library_float.cpp | 170 ++++++++++-- Tools/SeeDot/seedot/Predictor/library_float.h | 8 +- Tools/SeeDot/seedot/Predictor/main.cpp | 5 + .../seedot/compiler/ONNX/ONNXNodesAST.py | 99 ++++--- .../seedot/compiler/ONNX/onnx_test_run.py | 27 +- .../seedot/compiler/ONNX/paramsBuilderOnnx.py | 10 +- .../seedot/compiler/ONNX/process_onnx.py | 46 +++- Tools/SeeDot/seedot/compiler/ast/ast.py | 5 +- .../SeeDot/seedot/compiler/ast/astBuilder.py | 6 +- .../SeeDot/seedot/compiler/ast/astVisitor.py | 4 +- Tools/SeeDot/seedot/compiler/ast/mtdAST.py | 2 +- Tools/SeeDot/seedot/compiler/ast/printAST.py | 6 +- .../seedot/compiler/codegen/codegenBase.py | 28 +- Tools/SeeDot/seedot/compiler/codegen/x86.py | 7 +- Tools/SeeDot/seedot/compiler/compiler.py | 2 +- .../compiler/converter/paramsBuilder.py | 2 +- Tools/SeeDot/seedot/compiler/ir/irBuilder.py | 34 ++- Tools/SeeDot/seedot/compiler/type.py | 4 +- Tools/SeeDot/seedot/config.py | 9 +- Tools/SeeDot/seedot/main.py | 28 +- Tools/SeeDot/test/test.py | 245 ++++++------------ 24 files changed, 786 insertions(+), 331 deletions(-) diff --git a/Tools/SeeDot/SeeDot-dev.py b/Tools/SeeDot/SeeDot-dev.py index f6bc40d45..4f6cf076c 100644 --- a/Tools/SeeDot/SeeDot-dev.py +++ b/Tools/SeeDot/SeeDot-dev.py @@ -25,7 +25,7 @@ class Dataset: common = ["cifar-binary", "cr-binary", "cr-multiclass", "curet-multiclass", "letter-multiclass", "mnist-binary", "mnist-multiclass", "usps-binary", "usps-multiclass", "ward-binary", "test"] - extra = ["cifar-multiclass", "dsa", "eye-binary", "farm-beats", + extra = ["cifar-multiclass", "imagenet", "dsa", "eye-binary", "farm-beats", "interactive-cane", "spectakoms", "usps10", "whale-binary", "HAR-2", "HAR-6", "MNIST-10", "Google-12", "Google-30", "Wakeword-2", "wider-regression", "wider-mbconv", "face-1", "face-2"] @@ -51,8 +51,8 @@ def parseArgs(self): default=config.Version.default, metavar='', help="Floating-point or fixed-point") parser.add_argument("-d", "--dataset", choices=Dataset.all, default=Dataset.default, metavar='', help="Dataset to use") - parser.add_argument("-m", "--maximisingMetric", choices=config.MaximisingMetric.all, metavar='', - help="What metric to maximise during exploration",default=config.MaximisingMetric.default) + parser.add_argument("-m", "--metric", choices=config.Metric.all, metavar='', + help="What metric to maximise during exploration",default=config.Metric.default) parser.add_argument("-n", "--numOutputs", type=int, metavar='', help="Number of simultaneous outputs of the inference procedure",default=1) parser.add_argument("-dt", "--datasetType", choices=config.DatasetType.all, @@ -89,8 +89,8 @@ def parseArgs(self): self.args.datasetType = [self.args.datasetType] if not isinstance(self.args.target, list): self.args.target = [self.args.target] - if not isinstance(self.args.maximisingMetric, list): - self.args.maximisingMetric = [self.args.maximisingMetric] + if not isinstance(self.args.metric, list): + self.args.metric = [self.args.metric] if self.args.tempdir is not None: assert os.path.isdir( @@ -148,8 +148,8 @@ def runMainDriver(self): results = self.loadResultsFile() - for iter in product(self.args.algo, self.args.version, self.args.dataset, self.args.target, self.args.maximisingMetric, [16]): - algo, version, dataset, target, maximisingMetric, wordLength = iter + for iter in product(self.args.algo, self.args.version, self.args.dataset, self.args.target, self.args.metric, [16]): + algo, version, dataset, target, metric, wordLength = iter #config.wordLength = wordLength #config.maxScaleRange = 0, -wordLength @@ -243,7 +243,7 @@ def runMainDriver(self): numOutputs = self.args.numOutputs obj = main.Main(algo, version, target, trainingInput, - testingInput, modelDir, sf, maximisingMetric, dataset, numOutputs, self.args.source) + testingInput, modelDir, sf, metric, dataset, numOutputs, self.args.source) obj.run() acc = obj.testingAccuracy diff --git a/Tools/SeeDot/seedot/Predictor/library_fixed.cpp b/Tools/SeeDot/seedot/Predictor/library_fixed.cpp index 6db971fdd..e05f30f23 100644 --- a/Tools/SeeDot/seedot/Predictor/library_fixed.cpp +++ b/Tools/SeeDot/seedot/Predictor/library_fixed.cpp @@ -31,6 +31,34 @@ void MatAddNN(MYINT *A, MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT shrA, MYINT return; } +// C = A + B +void MatAddNN(MYINT *A, MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT K, MYINT L, MYINT shrA, MYINT shrB, MYINT shrC) +{ + for (MYITE i = 0; i < I; i++) + { + for (MYITE j = 0; j < J; j++) + { + for (MYITE k = 0; k < K; k++) + { + for (MYITE l = 0; l < L; l++) + { + MYINT a = A[i * J * K * L + j * K * L + k * L + l]; + MYINT b = B[i * J * K * L + j * K * L + k * L + l]; + + a = a / shrA; + b = b / shrB; + + MYINT c = Saturate(a / shrC + b / shrC); + + C[i * J * K * L + j * K * L + k * L + l] = c; + } + } + } + } + return; +} + + // C = A + B void MatAddCN(const MYINT *A, MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB, MYINT shrC) { @@ -618,6 +646,18 @@ void Transpose(MYINT *A, MYINT *B, MYINT I, MYINT J) return; } +void Transpose(const MYINT *A, MYINT *B, MYINT I, MYINT J) +{ + for (MYITE i = 0; i < I; i++) + { + for (MYITE j = 0; j < J; j++) + { + B[i * J + j] = A[j * I + i]; + } + } + return; +} + // C = a * B void ScalarMul(MYINT *A, MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB) { @@ -947,34 +987,124 @@ void Relu2D(MYINT *A, MYINT H, MYINT W) } // B = maxpool(A) -// A[N][H][W][C], B[N][H][W][C] -void Maxpool(MYINT *A, MYINT *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT HPADL, MYINT HPADR, MYINT WPADL, MYINT WPADR) +// A[N][inH][inW][C], B[N][outH][outW][C] +void Maxpool(MYINT *A, MYINT *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight) { - MYITE HO = H / strideH; - MYITE WO = W / strideW; for (MYITE n = 0; n < N; n++) - { - for (MYITE ho = 0; ho < HO; ho++) - { - for (MYITE wo = 0; wo < WO; wo++) - { - for (MYITE c = 0; c < C; c++) - { + { + for (MYITE c = 0; c < C; c++) + { + MYITE leftTopCornerH = 0 - zPadHLeft; + MYITE extremeRightBottomCornerH = H - 1 + zPadHRight; + MYITE ctH = 0; + + while((leftTopCornerH + FH - 1) <= extremeRightBottomCornerH){ + + MYITE leftTopCornerW = 0 - zPadWLeft; + MYITE extremeRightBottomCornerW = W - 1 + zPadWRight; + MYITE ctW = 0; + + while((leftTopCornerW + FW - 1) <= extremeRightBottomCornerW) + { + + MYINT maxi = 0; + if ((((leftTopCornerH < 0) || (leftTopCornerH >= H)) || ((leftTopCornerW < 0) || (leftTopCornerW >= W)))){ + maxi = 0; + } + else{ + // maxi = inArr[n][leftTopCornerH][leftTopCornerW][c]; + maxi = A[n * H * W * C + leftTopCornerH * W * C + leftTopCornerW * C + c]; + }; - MYINT max = A[n * H * W * C + (strideH * ho) * W * C + (strideW * wo) * C + c]; - for (MYITE hs = 0; hs < FH; hs++) + for (MYITE fh = 0; fh < FH; fh++) { - for (MYITE ws = 0; ws < FW; ws++) - { - MYINT a = A[n * H * W * C + ((strideH * ho) + hs) * W * C + ((strideW * wo) + ws) * C + c]; - if (a > max) - max = a; + for (MYITE fw = 0; fw < FW; fw++) + { + MYITE curPosH = leftTopCornerH + fh; + MYITE curPosW = leftTopCornerW + fw; + MYINT temp = 0; + + if ((((curPosH < 0) || (curPosH >= H)) || ((curPosW < 0) || (curPosW >= W)))){ + temp = 0; + } + else{ + // temp = inArr[n][curPosH][curPosW][c]; + temp = A[n * H * W * C + curPosH * W * C + curPosW * C + c]; + }; + maxi = ((maxi < temp) ? temp : maxi); + + } + } + + B[n * outH * outW * C + ctH * outW * C + ctW * C + c] = maxi; + // outArr[n][ctH][ctW][c] = maxi; + leftTopCornerW = leftTopCornerW + strideW; + ctW = ctW + 1; + } + + leftTopCornerH = leftTopCornerH + strideH; + ctH = ctH + 1; + } + } + } + + return; +} + +// B = avgpool(A) +// A[N][inH][inW][C], B[N][outH][outW][C] +void Avgpool(MYINT *A, MYINT *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight) +{ + MYINT FSIZE = FH*FW; + + for (MYITE n = 0; n < N; n++) + { + for (MYITE c = 0; c < C; c++) + { + MYITE leftTopCornerH = 0 - zPadHLeft; + MYITE extremeRightBottomCornerH = H - 1 + zPadHRight; + MYITE ctH = 0; + + while((leftTopCornerH + FH - 1) <= extremeRightBottomCornerH){ + + MYITE leftTopCornerW = 0 - zPadWLeft; + MYITE extremeRightBottomCornerW = W - 1 + zPadWRight; + MYITE ctW = 0; + + while((leftTopCornerW + FW - 1) <= extremeRightBottomCornerW) + { + + MYINT sum = 0; + + for (MYITE fh = 0; fh < FH; fh++) + { + for (MYITE fw = 0; fw < FW; fw++) + { + MYITE curPosH = leftTopCornerH + fh; + MYITE curPosW = leftTopCornerW + fw; + MYINT temp = 0; + + if ((((curPosH < 0) || (curPosH >= H)) || ((curPosW < 0) || (curPosW >= W)))){ + temp = 0; + } + else{ + // temp = inArr[n][curPosH][curPosW][c]; + temp = A[n * H * W * C + curPosH * W * C + curPosW * C + c]; + }; + sum = sum + temp; + } } - B[n * HO * WO * C + ho * WO * C + wo * C + c] = max; + B[n * outH * outW * C + ctH * outW * C + ctW * C + c] = sum/FSIZE; + // outArr[n][ctH][ctW][c] = maxi; + leftTopCornerW = leftTopCornerW + strideW; + ctW = ctW + 1; } + + leftTopCornerH = leftTopCornerH + strideH; + ctH = ctH + 1; } } } diff --git a/Tools/SeeDot/seedot/Predictor/library_fixed.h b/Tools/SeeDot/seedot/Predictor/library_fixed.h index c7ff747b0..f97a61ab0 100644 --- a/Tools/SeeDot/seedot/Predictor/library_fixed.h +++ b/Tools/SeeDot/seedot/Predictor/library_fixed.h @@ -4,7 +4,9 @@ #pragma once #include "datatypes.h" +#include +using namespace std; /** * Notation used: * By default, 'matrix' is to be interpreted as a matrix in fixed point representation @@ -36,6 +38,9 @@ void MatAddCN(const MYINT *A, MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT shrA, void MatAddNC(MYINT *A, const MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB, MYINT shrC); void MatAddCC(const MYINT *A, const MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB, MYINT shrC); +void MatAddNN(MYINT *A, MYINT *B, MYINT *C, MYINT I, MYINT J, MYINT K, MYINT L, MYINT shrA, MYINT shrB, MYINT shrC); + + /** * Dimensions: I, J, shrA, shrB, shrC are integers * C is a matrix, dim(C) = [I][J] @@ -159,6 +164,8 @@ void ArgMax(MYINT *A, MYINT I, MYINT J, MYINT *index); * Computes transpose(A) and stores the result in B */ void Transpose(MYINT *A, MYINT *B, MYINT I, MYINT J); +void Transpose(const MYINT *A, MYINT *B, MYINT I, MYINT J); + /** * Dimensions: I, J, shrA, shrB are integers @@ -238,12 +245,26 @@ void Relu6(MYINT *A, MYINT *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT six, MY * Computes the maxpool of A and stores the result in B * Raw parameters (directly passed from input code to function): * FH, FW : Size of filter amongst which max is taken - * HPADL, HPADR : Thickness of padding on top, bottom of the image - * WPADL, WPADR : Thickness of padding on left, right of the image + * zPadHLeft, zPadHRight : Thickness of padding on top, bottom of the image + * zPadWLeft, zPadWRight : Thickness of padding on left, right of the image * strideH, strideW : Convolution horizontal, vertical stride */ -void Maxpool(MYINT *A, MYINT *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT HPADL, MYINT HPADR, MYINT WPADL, MYINT WPADR); +void Maxpool(MYINT *A, MYINT *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight); + +/** + * Dimensions: A, B are matrices, dim(A) = dim(B) = [N][H][W][C]; N, H, W, C are integers + * FH, FW, strideH, strideW, HPADL, HPADR, WPADL, WPADR + * + * Avgpool + * Computes the average pool of A and stores the result in B + * Raw parameters (directly passed from input code to function): + * FH, FW : Size of filter amongst which max is taken + * zPadHLeft, zPadHRight : Thickness of padding on top, bottom of the image + * zPadWLeft, zPadWRight : Thickness of padding on left, right of the image + * strideH, strideW : Convolution horizontal, vertical stride + */ +void Avgpool(MYINT *A, MYINT *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight); /** * Dimensions: A is a tensor. dim(A) = [N][H][W][C] @@ -350,6 +371,36 @@ void MatAddNN(TypeA* A, TypeB* B, TypeC* C, MYINT I, MYINT J, MYINT shrA, MYINT } return; } + + +// C = A + B +template +void MatAddNN(TypeA *A, TypeB *B, TypeC *C, MYINT I, MYINT J, MYINT K, MYINT L, MYINT shrA, MYINT shrB, MYINT shrC, MYINT demote) +{ + for (MYITE i = 0; i < I; i++) + { + for (MYITE j = 0; j < J; j++) + { + for (MYITE k = 0; k < K; k++) + { + for (MYITE l = 0; l < L; l++) + { + TypeTemp a = A[i * J * K * L + j * K * L + k * L + l]; + TypeTemp b = B[i * J * K * L + j * K * L + k * L + l]; + + a = a / shrA; + b = b / shrB; + + TypeTemp c = a / shrC + b / shrC; + + C[i * J + j] = Saturate(c / demote); + } + } + } + } + return; +} + template void MatAddCN(const TypeA* A, TypeB* B, TypeC* C, MYINT I, MYINT J, MYINT shrA, MYINT shrB, MYINT shrC, MYINT demote) { for (MYITE i = 0; i < I; i++) { @@ -1211,30 +1262,129 @@ void Relu2D(TypeA* A, MYINT H, MYINT W) { return; } + +// B = maxpool(A) +// A[N][inH][inW][C], B[N][outH][outW][C] template -void Maxpool(TypeA* A, TypeB* B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT HPADL, MYINT HPADR, MYINT WPADL, MYINT WPADR, MYINT demote) { - MYITE HO = H / strideH; - MYITE WO = W / strideW; +void Maxpool(TypeA *A, TypeB *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight, MYINT demote) +{ + for (MYITE n = 0; n < N; n++) + { + for (MYITE c = 0; c < C; c++) + { + MYITE leftTopCornerH = 0 - zPadHLeft; + MYITE extremeRightBottomCornerH = H - 1 + zPadHRight; + MYITE ctH = 0; - for (MYITE n = 0; n < N; n++) { - for (MYITE ho = 0; ho < HO; ho++) { - for (MYITE wo = 0; wo < WO; wo++) { - for (MYITE c = 0; c < C; c++) { + while((leftTopCornerH + FH - 1) <= extremeRightBottomCornerH){ + + MYITE leftTopCornerW = 0 - zPadWLeft; + MYITE extremeRightBottomCornerW = W - 1 + zPadWRight; + MYITE ctW = 0; + + while((leftTopCornerW + FW - 1) <= extremeRightBottomCornerW) + { + + TypeA maxi = 0; + if ((((leftTopCornerH < 0) || (leftTopCornerH >= H)) || ((leftTopCornerW < 0) || (leftTopCornerW >= W)))){ + maxi = 0; + } + else{ + // maxi = inArr[n][leftTopCornerH][leftTopCornerW][c]; + maxi = A[n * H * W * C + leftTopCornerH * W * C + leftTopCornerW * C + c]; + }; + + for (MYITE fh = 0; fh < FH; fh++) + { + for (MYITE fw = 0; fw < FW; fw++) + { + MYITE curPosH = leftTopCornerH + fh; + MYITE curPosW = leftTopCornerW + fw; + MYITE temp = 0; + if ((((curPosH < 0) || (curPosH >= H)) || ((curPosW < 0) || (curPosW >= W)))){ + temp = 0; + } + else{ + // temp = inArr[n][curPosH][curPosW][c]; + temp = A[n * H * W * C + curPosH * W * C + curPosW * C + c]; + }; + maxi = ((maxi < temp) ? temp : maxi); - TypeA max = A[n * H * W * C + (strideH * ho) * W * C + (strideW * wo) * C + c]; - for (MYITE hs = 0; hs < FH; hs++) { - for (MYITE ws = 0; ws < FW; ws++) { - TypeA a = A[n * H * W * C + ((strideH * ho) + hs) * W * C + ((strideW * wo) + ws) * C + c]; - if (a > max) - max = a; } } - B[n * HO * WO * C + ho * WO * C + wo * C + c] = (TypeB)(max / demote); + B[n * outH * outW * C + ctH * outW * C + ctW * C + c] = (TypeB) (maxi/demote); + // outArr[n][ctH][ctW][c] = maxi; + leftTopCornerW = leftTopCornerW + strideW; + ctW = ctW + 1; } + + leftTopCornerH = leftTopCornerH + strideH; + ctH = ctH + 1; } - } + } } + + return; +} + +// B = avgpool(A) +// A[N][inH][inW][C], B[N][outH][outW][C] +template +void Avgpool(TypeA *A, TypeB *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight, MYINT demote) +{ + MYINT FSIZE = FH*FW; + + for (MYITE n = 0; n < N; n++) + { + for (MYITE c = 0; c < C; c++) + { + MYITE leftTopCornerH = 0 - zPadHLeft; + MYITE extremeRightBottomCornerH = H - 1 + zPadHRight; + MYITE ctH = 0; + + while((leftTopCornerH + FH - 1) <= extremeRightBottomCornerH){ + + MYITE leftTopCornerW = 0 - zPadWLeft; + MYITE extremeRightBottomCornerW = W - 1 + zPadWRight; + MYITE ctW = 0; + + while((leftTopCornerW + FW - 1) <= extremeRightBottomCornerW) + { + + TypeA sum = 0; + + for (MYITE fh = 0; fh < FH; fh++) + { + for (MYITE fw = 0; fw < FW; fw++) + { + MYITE curPosH = leftTopCornerH + fh; + MYITE curPosW = leftTopCornerW + fw; + MYITE temp = 0; + if ((((curPosH < 0) || (curPosH >= H)) || ((curPosW < 0) || (curPosW >= W)))){ + temp = 0; + } + else{ + // temp = inArr[n][curPosH][curPosW][c]; + temp = A[n * H * W * C + curPosH * W * C + curPosW * C + c]; + }; + sum = sum + temp; + + } + } + + B[n * outH * outW * C + ctH * outW * C + ctW * C + c] = (TypeB) ((sum/FSIZE)/demote); + // outArr[n][ctH][ctW][c] = maxi; + leftTopCornerW = leftTopCornerW + strideW; + ctW = ctW + 1; + } + + leftTopCornerH = leftTopCornerH + strideH; + ctH = ctH + 1; + } + } + } + return; } diff --git a/Tools/SeeDot/seedot/Predictor/library_float.cpp b/Tools/SeeDot/seedot/Predictor/library_float.cpp index 93713c09e..09b1ceec9 100644 --- a/Tools/SeeDot/seedot/Predictor/library_float.cpp +++ b/Tools/SeeDot/seedot/Predictor/library_float.cpp @@ -26,6 +26,30 @@ void MatAddNN(float *A, float *B, float *C, MYINT I, MYINT J, MYINT shrA, MYINT return; } +// C = A + B +void MatAddNN(float *A, float *B, float *C, MYINT I, MYINT J, MYINT K, MYINT L, MYINT shrA, MYINT shrB, MYINT shrC) +{ + for (MYITE i = 0; i < I; i++) + { + for (MYITE j = 0; j < J; j++) + { + for (MYITE k = 0; k < K; k++) + { + for (MYITE l = 0; l < L; l++) + { + float a = A[i * J * K * L + j * K * L + k * L + l]; + float b = B[i * J * K * L + j * K * L + k * L + l]; + + float c = a + b; + + C[i * J * K * L + j * K * L + k * L + l] = c; + } + } + } + } + return; +} + // C = A + B void MatAddCN(const float *A, float *B, float *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB, MYINT shrC) { @@ -515,6 +539,18 @@ void Transpose(float *A, float *B, MYINT I, MYINT J) return; } +void Transpose(const float *A, float *B, MYINT I, MYINT J) +{ + for (MYITE i = 0; i < I; i++) + { + for (MYITE j = 0; j < J; j++) + { + B[i * J + j] = A[j * I + i]; + } + } + return; +} + // C = a * B void ScalarMul(float *A, float *B, float *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB) { @@ -947,35 +983,131 @@ void Relu2D(float *A, MYINT H, MYINT W) return; } +using namespace std; + // B = maxpool(A) -// A[N][H][W][C], B[N][H][W][C] -void Maxpool(float *A, float *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT HPADL, MYINT HPADR, MYINT WPADL, MYINT WPADR) +// A[N][inH][inW][C], B[N][outH][outW][C] +void Maxpool(float *A, float *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight) { - MYITE HO = H / strideH; - MYITE WO = W / strideW; + for (MYITE n = 0; n < N; n++) + { + for (MYITE c = 0; c < C; c++) + { + MYITE leftTopCornerH = 0 - zPadHLeft; + MYITE extremeRightBottomCornerH = H - 1 + zPadHRight; + MYITE ctH = 0; + + while((leftTopCornerH + FH - 1) <= extremeRightBottomCornerH){ + + MYITE leftTopCornerW = 0 - zPadWLeft; + MYITE extremeRightBottomCornerW = W - 1 + zPadWRight; + MYITE ctW = 0; + + while((leftTopCornerW + FW - 1) <= extremeRightBottomCornerW) + { + + float maxi = 0; + if ((((leftTopCornerH < 0) || (leftTopCornerH >= H)) || ((leftTopCornerW < 0) || (leftTopCornerW >= W)))){ + maxi = 0; + } + else{ + // maxi = inArr[n][leftTopCornerH][leftTopCornerW][c]; + maxi = A[n * H * W * C + leftTopCornerH * W * C + leftTopCornerW * C + c]; + }; + + for (MYITE fh = 0; fh < FH; fh++) + { + for (MYITE fw = 0; fw < FW; fw++) + { + MYITE curPosH = leftTopCornerH + fh; + MYITE curPosW = leftTopCornerW + fw; + float temp = 0; + + if ((((curPosH < 0) || (curPosH >= H)) || ((curPosW < 0) || (curPosW >= W)))){ + temp = 0; + } + else{ + // temp = inArr[n][curPosH][curPosW][c]; + temp = A[n * H * W * C + curPosH * W * C + curPosW * C + c]; + }; + maxi = ((maxi < temp) ? temp : maxi); + + } + } + + // cout << "ABC" << endl; + // cout << ctH << ' ' << ctW << ' ' << maxi << endl; + B[n * outH * outW * C + ctH * outW * C + ctW * C + c] = maxi; + // outArr[n][ctH][ctW][c] = maxi; + leftTopCornerW = leftTopCornerW + strideW; + ctW = ctW + 1; + } + + leftTopCornerH = leftTopCornerH + strideH; + ctH = ctH + 1; + } + } + } + + return; +} + + +// B = avgpool(A) +// A[N][inH][inW][C], B[N][outH][outW][C] +void Avgpool(float *A, float *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight) +{ + MYINT FSIZE = FH*FW; for (MYITE n = 0; n < N; n++) - { - for (MYITE ho = 0; ho < HO; ho++) - { - for (MYITE wo = 0; wo < WO; wo++) - { - for (MYITE c = 0; c < C; c++) - { + { + for (MYITE c = 0; c < C; c++) + { + MYITE leftTopCornerH = 0 - zPadHLeft; + MYITE extremeRightBottomCornerH = H - 1 + zPadHRight; + MYITE ctH = 0; - float max = A[n * H * W * C + (strideH * ho) * W * C + (strideW * wo) * C + c]; - for (MYITE hs = 0; hs < FH; hs++) + while((leftTopCornerH + FH - 1) <= extremeRightBottomCornerH){ + + MYITE leftTopCornerW = 0 - zPadWLeft; + MYITE extremeRightBottomCornerW = W - 1 + zPadWRight; + MYITE ctW = 0; + + while((leftTopCornerW + FW - 1) <= extremeRightBottomCornerW) + { + + float sum = 0; + + for (MYITE fh = 0; fh < FH; fh++) { - for (MYITE ws = 0; ws < FW; ws++) - { - float a = A[n * H * W * C + ((strideH * ho) + hs) * W * C + ((strideW * wo) + ws) * C + c]; - if (a > max) - max = a; + for (MYITE fw = 0; fw < FW; fw++) + { + MYITE curPosH = leftTopCornerH + fh; + MYITE curPosW = leftTopCornerW + fw; + float temp = 0; + + if ((((curPosH < 0) || (curPosH >= H)) || ((curPosW < 0) || (curPosW >= W)))){ + temp = 0; + } + else{ + // temp = inArr[n][curPosH][curPosW][c]; + temp = A[n * H * W * C + curPosH * W * C + curPosW * C + c]; + }; + sum = sum + temp; + } } - B[n * HO * WO * C + ho * WO * C + wo * C + c] = max; + // cout << "ABC" << endl; + // cout << ctH << ' ' << ctW << ' ' << maxi << endl; + B[n * outH * outW * C + ctH * outW * C + ctW * C + c] = sum/FSIZE; + // outArr[n][ctH][ctW][c] = maxi; + leftTopCornerW = leftTopCornerW + strideW; + ctW = ctW + 1; } + + leftTopCornerH = leftTopCornerH + strideH; + ctH = ctH + 1; } } } diff --git a/Tools/SeeDot/seedot/Predictor/library_float.h b/Tools/SeeDot/seedot/Predictor/library_float.h index 95b091ca0..b745b73e6 100644 --- a/Tools/SeeDot/seedot/Predictor/library_float.h +++ b/Tools/SeeDot/seedot/Predictor/library_float.h @@ -22,6 +22,9 @@ void MatMulCN(const float *A, float *B, float *C, float *tmp, MYINT I, MYINT K, void MatMulNC(float *A, const float *B, float *C, float *tmp, MYINT I, MYINT K, MYINT J, MYINT shrA, MYINT shrB, MYINT H1, MYINT H2); void MatMulCC(const float *A, const float *B, float *C, float *tmp, MYINT I, MYINT K, MYINT J, MYINT shrA, MYINT shrB, MYINT H1, MYINT H2); +void MatAddNN(float *A, float *B, float *C, MYINT I, MYINT J, MYINT K, MYINT L, MYINT shrA, MYINT shrB, MYINT shrC); + + void SparseMatMul(const MYINT *Aidx, const float *Aval, float **B, float *C, int16_t K, MYINT shrA, MYINT shrB, MYINT shrC); void MulCir(float *A, float *B, float *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB); @@ -31,6 +34,7 @@ void TanH(float *A, MYINT I, MYINT J, float scale_in, float scale_out, float *B) void ArgMax(float *A, MYINT I, MYINT J, MYINT *index); void Transpose(float *A, float *B, MYINT I, MYINT J); +void Transpose(const float *A, float *B, MYINT I, MYINT J); void ScalarMul(float *A, float *B, float *C, MYINT I, MYINT J, MYINT shrA, MYINT shrB); @@ -50,7 +54,9 @@ void Relu2D(float *A, MYINT H, MYINT W); void Relu6(float *A, float *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT six, MYINT div); -void Maxpool(float *A, float *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT HPADL, MYINT HPADR, MYINT WPADL, MYINT WPADR); +void Maxpool(float *A, float *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight); + +void Avgpool(float *A, float *B, MYINT N, MYINT H, MYINT W, MYINT C, MYINT outH, MYINT outW, MYINT FH, MYINT FW, MYINT strideH, MYINT strideW, MYINT zPadHLeft, MYINT zPadHRight, MYINT zPadWLeft, MYINT zPadWRight); void Exp(float *A, MYINT I, MYINT J, MYINT shrA, MYINT shrB, float *B); diff --git a/Tools/SeeDot/seedot/Predictor/main.cpp b/Tools/SeeDot/seedot/Predictor/main.cpp index c60e0b4bd..ad19b9019 100644 --- a/Tools/SeeDot/seedot/Predictor/main.cpp +++ b/Tools/SeeDot/seedot/Predictor/main.cpp @@ -345,6 +345,9 @@ int main(int argc, char *argv[]) } + string computedOutputFile = outputDir + "/output-" + datasetTypeStr + ".txt"; + ofstream computedOutput(computedOutputFile); + float disagreements = 0.0, reduced_disagreements = 0.0; vector correctV(switches, 0), totalV(switches, 0); @@ -410,8 +413,10 @@ int main(int argc, char *argv[]) float res; if (version == Float) { res = float_res[j]; + computedOutput << res << endl; } else { res = ((float) fixed_res[j]) / ldexp(1.0 , -scaleForY); + computedOutput << res << endl; } float error = 100.0 * fabs(res - labelsFloat[i][j]) / (epsilon + fabs(labelsFloat[i][j])); diff --git a/Tools/SeeDot/seedot/compiler/ONNX/ONNXNodesAST.py b/Tools/SeeDot/seedot/compiler/ONNX/ONNXNodesAST.py index a65e36b01..03b51b578 100644 --- a/Tools/SeeDot/seedot/compiler/ONNX/ONNXNodesAST.py +++ b/Tools/SeeDot/seedot/compiler/ONNX/ONNXNodesAST.py @@ -177,7 +177,12 @@ def get_reshaped_bias_ast(bias_name, value_info, node_name_to_out_var_dict, dim) def get_reshaped_filter_ast(filter_name, value_info, node_name_to_out_var_dict): onnx_filter_shape = list(value_info[filter_name][1]) (seedot_filter_shape, seedot_filter_order) = get_seedot_filter_shape_order(onnx_filter_shape) - return AST.Reshape(AST.ID(node_name_to_out_var_dict[filter_name]), seedot_filter_shape, seedot_filter_order) + return AST.Reshape(AST.ID(node_name_to_out_var_dict[filter_name]), seedot_filter_shape, seedot_filter_order) + +def get_reshaped_bn_scale_as_conv_filter_ast(filter_name, value_info, node_name_to_out_var_dict): + onnx_scale_shape = value_info[filter_name][1][0] + (seedot_filter_shape, seedot_filter_order) = ([onnx_scale_shape,1,1,1,1], None) + return AST.Reshape(AST.ID(node_name_to_out_var_dict[filter_name]), seedot_filter_shape, seedot_filter_order) def get_reshaped_output_ast(onnx_output_name, value_info, output_name): onnx_output_shape = list(value_info[onnx_output_name][1]) @@ -210,11 +215,16 @@ def Input(node, value_info, node_name_to_out_var_dict, init_val=None): # return AST.Input(dims, onnx2seedot(data_type)) from onnx import numpy_helper - range = (-3,3) + # TODO: extract the range from training file + # for imagenet + range = (0,250) + # for lenet + # range = (-3, 3) + + if init_val is not None: - arr = numpy_helper.to_array(init_val) - range = (np.min(arr),np.max(arr)) + range = (np.min(init_val),np.max(init_val)) return AST.Decl(dims, range) @@ -398,8 +408,8 @@ def Add(node, value_info, node_name_to_out_var_dict, innermost_let_ast_node, out innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, reshaped_input1, reshaped_input_name1, mtdAST) out_var_count += 1 - seedot_output_ast = AST.BOp(AST.ID(reshaped_input_name), - getOperatorsIdx('+'), + seedot_output_ast = AST.Bop2(AST.ID(reshaped_input_name), + SeeDotParser.ADD, AST.ID(reshaped_input_name1) ) output_name = get_new_var_name(out_var_count) @@ -523,28 +533,57 @@ def BatchNormalization(node, value_info, node_name_to_out_var_dict, innermost_le # Are running mean and var used for something? assert(len(inputsRef)==5) + # inputsRef = node.inputs + inputShape = value_info[inputsRef[0]][1] + filterShape = value_info[inputsRef[1]][1] + + stridesUsed = [1,1] + group = value_info[inputsRef[1]][1][0] + padding = [0,0,0,0] + dilation = [1,1] + + # BN has 5 inputs. Though we are preprocessing them and reducing it to 3 (input, scale, bias) + # Last 2 inputs are unused + assert(len(inputsRef)==5) + assert(len(stridesUsed)==2) + + # we assume VALID case when the padding is in string format + + # print(inputShape, filterShape) + #in case of BN filter has only one dimension i.e. number of channels + assert (inputShape[1] == group) + # For Input: + # [N, CI, H, W] is the Onnx order it should be changed to + # [N, H, W, CI] order reshaped_input_name = get_new_var_name(out_var_count) reshaped_input = get_reshaped_input_ast(inputsRef[0], value_info, node_name_to_out_var_dict) innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, reshaped_input, reshaped_input_name, mtdAST) out_var_count += 1 - seedot_output_ast = AST.FusedBatchNorm(AST.ID(reshaped_input_name), - AST.ID(node_name_to_out_var_dict[inputsRef[1]]), - AST.ID(node_name_to_out_var_dict[inputsRef[2]]), - ) + # For filter: + # [CO, CI1, FH, FW] is the Onnx order it should be changed to + # [FH, FW, CI1, CO] order + reshaped_filter_name = get_new_var_name(out_var_count) + reshaped_filter = get_reshaped_bn_scale_as_conv_filter_ast(inputsRef[1], value_info, node_name_to_out_var_dict) + innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, reshaped_filter, reshaped_filter_name, mtdAST) + out_var_count += 1 + + seedot_output_ast = AST.Convolution(AST.ID(reshaped_input_name), AST.ID(reshaped_filter_name), stridesUsed, padding, dilation, group) + output_name = get_new_var_name(out_var_count) + innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, seedot_output_ast, output_name, mtdAST) + out_var_count += 1 + + # If there is bias to be added then reshape and add it + seedot_output_ast = AST.Bop1(AST.ID(output_name), SeeDotParser.ADDCIR, AST.ID(inputsRef[2])) output_name = get_new_var_name(out_var_count) innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, seedot_output_ast, output_name, mtdAST) out_var_count += 1 reshaped_output_name = get_new_var_name(out_var_count) - onnx_output_ast = get_reshaped_output_ast(node.outputs[0], value_info, output_name) - innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, onnx_output_ast, reshaped_output_name, mtdAST) + onnx_output_ast = get_reshaped_output_ast(node.outputs[0],value_info, output_name) + innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, onnx_output_ast, reshaped_output_name, mtdAST) out_var_count += 1 node_name_to_out_var_dict[node.outputs[0]] = reshaped_output_name - - if(DEBUG): - print(node.outputs[0]) - print(onnx_input_shape, '->', seedot_input_shape, '->', onnx_output_shape) return (innermost_let_ast_node, out_var_count) @@ -718,19 +757,15 @@ def GlobalAveragePool(node, value_info, node_name_to_out_var_dict, innermost_let innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, reshaped_input, reshaped_input_name, mtdAST) out_var_count += 1 - seedot_output_ast = AST.Pool(AST.Pool.PoolType.AvgPool, + stridesUsed = [1,1] + kernelSize = [value_info[inputsRef[0]][1][2], value_info[inputsRef[0]][1][3]] + padding = [0,0,0,0] + + seedot_output_ast = AST.Pool( AST.ID(reshaped_input_name), - { - AST.PaddingKeysDict.FH: value_info[inputsRef[0]][1][2], - AST.PaddingKeysDict.FW: value_info[inputsRef[0]][1][3], - AST.PaddingKeysDict.zPadHLeft: 0, - AST.PaddingKeysDict.zPadHRight: 0, - AST.PaddingKeysDict.zPadWLeft: 0, - AST.PaddingKeysDict.zPadWRight: 0, - AST.PaddingKeysDict.strideH: 1, - AST.PaddingKeysDict.strideW: 1 - } - ) + kernelSize, padding, stridesUsed, "avgpool" + ) + output_name = get_new_var_name(out_var_count) innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, seedot_output_ast, output_name, mtdAST) out_var_count += 1 @@ -762,14 +797,14 @@ def helper_processPool(node, value_info, node_name_to_out_var_dict, innermost_le out_var_count += 1 poolType = None - if typeOfPool=='MAXPOOL': poolType = AST.Maxpool - elif typeOfPool=='AVGPOOL': poolType = AST.Avgpool + if typeOfPool=='MAXPOOL': poolType = "maxpool" + elif typeOfPool=='AVGPOOL': poolType = "avgpool" else: print("Unknown type of pooling layer.", file=sys.stderr) assert(False) - seedot_output_ast = poolType( + seedot_output_ast = AST.Pool( AST.ID(reshaped_input_name), - kernelSize, padding, stridesUsed + kernelSize, padding, stridesUsed, poolType ) output_name = get_new_var_name(out_var_count) innermost_let_ast_node = update_program_with_new_node(innermost_let_ast_node, seedot_output_ast, output_name, mtdAST) diff --git a/Tools/SeeDot/seedot/compiler/ONNX/onnx_test_run.py b/Tools/SeeDot/seedot/compiler/ONNX/onnx_test_run.py index 55f0296cd..3e48acd88 100644 --- a/Tools/SeeDot/seedot/compiler/ONNX/onnx_test_run.py +++ b/Tools/SeeDot/seedot/compiler/ONNX/onnx_test_run.py @@ -30,14 +30,14 @@ import onnx from onnx import helper -file_path = '../../../model/lenet/cifar-multiclass/input.onnx' +file_path = '../../../model/resnet-18/imagenet/input.onnx' model = onnx.load(file_path) sess = onnxruntime.InferenceSession(file_path) -dataset_path = '../../../datasets/lenet/cifar-multiclass/test_onnx.npy' +dataset_path = '../../../datasets/resnet-18/imagenet/test.npy' test = np.load(dataset_path) -run_all = True +run_all = False intermediate = None correct = 0 @@ -49,7 +49,8 @@ output = test[i,0] # print(x.shape) - # print(output) + print(test[i].shape) + print(output) input_name = model.graph.input[0].name x = x.astype(np.float32) @@ -72,12 +73,18 @@ pred = sess.run(None, {input_name: x}) - predicted_class = pred[0][0]+1 - print(predicted_class) - print(int(output)) + # print(pred[0][0]) - correct += (predicted_class == int(output)) - total += 1 + print(pred[0].reshape(-1,1)) + + # # print(pred) + + # predicted_class = pred[0][0]+1 + # # print(predicted_class) + # print(int(output)) + + # correct += (predicted_class == int(output)) + # total += 1 # np.save('debug/' + model_name + '/' + model_name + '_output', pred) # with open('debug/onnx_output.txt', 'w') as f: @@ -85,4 +92,4 @@ # output_dims = common.proto_val_to_dimension_tuple(model.graph.output[0]) # print("Saving the onnx runtime output of dimension " + str(output_dims)) -print(str((float(correct)*100)/float(total)) + '% is the accuracy') +# print(str((float(correct)*100)/float(total)) + '% is the accuracy') diff --git a/Tools/SeeDot/seedot/compiler/ONNX/paramsBuilderOnnx.py b/Tools/SeeDot/seedot/compiler/ONNX/paramsBuilderOnnx.py index 92f8ce2c1..6a3a46711 100644 --- a/Tools/SeeDot/seedot/compiler/ONNX/paramsBuilderOnnx.py +++ b/Tools/SeeDot/seedot/compiler/ONNX/paramsBuilderOnnx.py @@ -54,6 +54,8 @@ def getParams(file_path): model_name_to_val_dict = { init_vals.name: numpy_helper.to_array(init_vals).tolist() for init_vals in model.graph.initializer} + preprocess_batch_normalization(graph_def, model_name_to_val_dict) + paramList = [] for init_vals in model.graph.initializer: @@ -61,7 +63,7 @@ def getParams(file_path): shape = numpy_helper.to_array(init_vals).shape range = get_range(numpy_helper.to_array(init_vals)) param = Param(name, shape, range) - param.data = numpy_helper.to_array(init_vals).reshape((1,-1)).tolist() + param.data = np.array(model_name_to_val_dict[name]).reshape(1,-1).tolist() paramList.append(param) return paramList @@ -81,9 +83,11 @@ def preprocess_batch_normalization(graph_def, model_name_to_val_dict): var = model_name_to_val_dict[node.input[4]] for i in range(len(gamma)): rsigma = 1/math.sqrt(var[i]+1e-5) + # print(gamma[i]," --> ",gamma[i]*rsigma) gamma[i] = gamma[i]*rsigma + # print(beta[i]," --> ", beta[i]-gamma[i]*mean[i]) beta[i] = beta[i]-gamma[i]*mean[i] - mean[i] = 0 + mean[i] = 1e-5 var[i] = 1-1e-5 # Just testing if the correct values are put @@ -96,7 +100,7 @@ def preprocess_batch_normalization(graph_def, model_name_to_val_dict): if(node.op_type == 'BatchNormalization'): mean = model_name_to_val_dict[node.input[3]] for val in mean: - assert(val == 0) + assert(val < 1e-4) if __name__ == "__main__": main() \ No newline at end of file diff --git a/Tools/SeeDot/seedot/compiler/ONNX/process_onnx.py b/Tools/SeeDot/seedot/compiler/ONNX/process_onnx.py index 2b9603611..0d1cd8a53 100644 --- a/Tools/SeeDot/seedot/compiler/ONNX/process_onnx.py +++ b/Tools/SeeDot/seedot/compiler/ONNX/process_onnx.py @@ -46,12 +46,15 @@ import seedot.compiler.ONNX.common as common import numpy as np +from onnx import numpy_helper +import math + np.set_printoptions(threshold=np.inf) DEBUG = False out_var_prefix = "J" -def process_input_variables(program, innermost_let_ast_node, node_name_to_out_var_dict, out_var_count, mtdAST, graph_def, value_info): +def process_input_variables(program, innermost_let_ast_node, node_name_to_out_var_dict, out_var_count, mtdAST, graph_def, value_info, model_name_to_val_dict): node = graph_def.input[0] curAst = ONNXNodesAST.Input(node, value_info, node_name_to_out_var_dict) mtdForCurAST = {AST.ASTNode.mtdKeyTFOpName : 'Input', @@ -78,7 +81,7 @@ def process_input_variables(program, innermost_let_ast_node, node_name_to_out_va print("Node information") print(node) - curAst = ONNXNodesAST.Input(node, value_info, node_name_to_out_var_dict, node) + curAst = ONNXNodesAST.Input(node, value_info, node_name_to_out_var_dict, model_name_to_val_dict[node.name]) mtdForCurAST = {AST.ASTNode.mtdKeyTFOpName : 'Input', AST.ASTNode.mtdKeyTFNodeName : node.name} if (curAst is None): @@ -115,6 +118,40 @@ def process_onnx_nodes(innermost_let_ast_node, node_name_to_out_var_dict, out_va assert(type(innermost_let_ast_node) is AST.Let) +def preprocess_batch_normalization(graph_def, model_name_to_val_dict): + # set names to graph nodes if not present + for node in graph_def.node: + node.name = node.output[0] + # Update the batch normalization scale and B + # so that mean and var are not required + if(node.op_type == 'BatchNormalization'): + # scale + gamma = model_name_to_val_dict[node.input[1]] + # B + beta = model_name_to_val_dict[node.input[2]] + mean = model_name_to_val_dict[node.input[3]] + var = model_name_to_val_dict[node.input[4]] + for i in range(len(gamma)): + rsigma = 1/math.sqrt(var[i]+1e-5) + # print(gamma[i]," --> ",gamma[i]*rsigma) + gamma[i] = gamma[i]*rsigma + # print(beta[i]," --> ", beta[i]-gamma[i]*mean[i]) + beta[i] = beta[i]-gamma[i]*mean[i] + mean[i] = 1e-5 + var[i] = 1-1e-5 + + # Just testing if the correct values are put + model_name_to_val_dict2 = {} + for init_vals in graph_def.initializer: + # TODO: Remove float_data + model_name_to_val_dict2[init_vals.name] = init_vals.float_data + for node in graph_def.node: + node.name = node.output[0] + if(node.op_type == 'BatchNormalization'): + mean = model_name_to_val_dict[node.input[3]] + for val in mean: + assert(val < 1e-4) + def get_seedot_ast(file_path): sys.setrecursionlimit(10000) print(os.getcwd()) @@ -156,7 +193,10 @@ def get_seedot_ast(file_path): out_var_count = 0 mtdAST = MtdAST() - (program, innermost_let_ast_node, out_var_count) = process_input_variables(program, innermost_let_ast_node, node_name_to_out_var_dict, out_var_count, mtdAST, graph_def, value_info) + model_name_to_val_dict = { init_vals.name: numpy_helper.to_array(init_vals).tolist() for init_vals in model.graph.initializer} + preprocess_batch_normalization(graph_def, model_name_to_val_dict) + + (program, innermost_let_ast_node, out_var_count) = process_input_variables(program, innermost_let_ast_node, node_name_to_out_var_dict, out_var_count, mtdAST, graph_def, value_info, model_name_to_val_dict) process_onnx_nodes(innermost_let_ast_node, node_name_to_out_var_dict, out_var_count, mtdAST, graph_def, value_info) diff --git a/Tools/SeeDot/seedot/compiler/ast/ast.py b/Tools/SeeDot/seedot/compiler/ast/ast.py index 3e3655236..b50fd0428 100644 --- a/Tools/SeeDot/seedot/compiler/ast/ast.py +++ b/Tools/SeeDot/seedot/compiler/ast/ast.py @@ -84,14 +84,15 @@ def __init__(self, expr, shape, order): self.order = order -class Maxpool(ASTNode): +class Pool(ASTNode): - def __init__(self, expr, kernelSize: list, padding: list, stride: list): + def __init__(self, expr, kernelSize: list, padding: list, stride: list, poolType: str): super().__init__() self.expr = expr self.kernelSize = kernelSize self.padding = padding self.stride = stride + self.poolType = poolType class Index(ASTNode): diff --git a/Tools/SeeDot/seedot/compiler/ast/astBuilder.py b/Tools/SeeDot/seedot/compiler/ast/astBuilder.py index e4a0d9404..b56ad7eba 100644 --- a/Tools/SeeDot/seedot/compiler/ast/astBuilder.py +++ b/Tools/SeeDot/seedot/compiler/ast/astBuilder.py @@ -65,12 +65,14 @@ def visitReshape(self, ctx: SeeDotParser.ReshapeContext): for IntConst in ctx.intConstList(1).IntConst()] return AST.Reshape(expr, shape, order) - def visitMaxpool(self, ctx: SeeDotParser.MaxpoolContext): + # Other pool types are not yet added in the SeeDot grammar + # those work from other frontends + def visitpool(self, ctx: SeeDotParser.MaxpoolContext): expr = self.visit(ctx.expr()) kernelSize = [int(ctx.IntConst(i).getText()) for i in range(0, 2)] padding = [int(ctx.IntConst(i).getText()) for i in range(2, 6)] stride = [int(ctx.IntConst(i).getText()) for i in range(6, 8)] - return AST.Maxpool(expr, kernelSize, padding, stride) + return AST.pool(expr, kernelSize, padding, stride, "maxpool") def visitReverse(self, ctx: SeeDotParser.MaxpoolContext): expr = self.visit(ctx.expr()) diff --git a/Tools/SeeDot/seedot/compiler/ast/astVisitor.py b/Tools/SeeDot/seedot/compiler/ast/astVisitor.py index adc7eae20..b4092bf29 100644 --- a/Tools/SeeDot/seedot/compiler/ast/astVisitor.py +++ b/Tools/SeeDot/seedot/compiler/ast/astVisitor.py @@ -29,8 +29,8 @@ def visit(self, node): return self.visitTransp(node) elif isinstance(node, AST.Reshape): return self.visitReshape(node) - elif isinstance(node, AST.Maxpool): - return self.visitMaxpool(node) + elif isinstance(node, AST.Pool): + return self.visitPool(node) elif isinstance(node, AST.Reverse): return self.visitReverse(node) elif isinstance(node, AST.Index): diff --git a/Tools/SeeDot/seedot/compiler/ast/mtdAST.py b/Tools/SeeDot/seedot/compiler/ast/mtdAST.py index 4b8923593..da77f7fec 100644 --- a/Tools/SeeDot/seedot/compiler/ast/mtdAST.py +++ b/Tools/SeeDot/seedot/compiler/ast/mtdAST.py @@ -23,7 +23,7 @@ def visitReshape(self, node: AST.Reshape, mtd: dict): node.metadata.update(mtd) self.visit(node.expr, mtd) - def visitMaxpool(self, node: AST.Maxpool, mtd: dict): + def visitPool(self, node: AST.Pool, mtd: dict): node.metadata.update(mtd) self.visit(node.expr, mtd) diff --git a/Tools/SeeDot/seedot/compiler/ast/printAST.py b/Tools/SeeDot/seedot/compiler/ast/printAST.py index 3ae51e773..dfef65dae 100644 --- a/Tools/SeeDot/seedot/compiler/ast/printAST.py +++ b/Tools/SeeDot/seedot/compiler/ast/printAST.py @@ -10,7 +10,7 @@ import seedot.compiler.ast.ast as AST from seedot.compiler.ast.astVisitor import ASTVisitor -indent = " " +indent = "" class PrintAST(ASTVisitor): @@ -47,9 +47,9 @@ def visitReshape(self, node: AST.Reshape): self.visit(node.expr) print(indent * node.printLevel, node.shape, "order", node.order) - def visitMaxpool(self, node: AST.Maxpool): + def visitPool(self, node: AST.Pool): node.expr.printLevel = node.printLevel + 1 - print(indent * node.printLevel, "maxpool") + print(indent * node.printLevel, node.poolType) self.visit(node.expr) print(indent * node.printLevel, node.kernelSize, node.stride, node.padding) diff --git a/Tools/SeeDot/seedot/compiler/codegen/codegenBase.py b/Tools/SeeDot/seedot/compiler/codegen/codegenBase.py index 0f298c552..7013cfb20 100644 --- a/Tools/SeeDot/seedot/compiler/codegen/codegenBase.py +++ b/Tools/SeeDot/seedot/compiler/codegen/codegenBase.py @@ -16,6 +16,8 @@ class CodegenBase: + dynamic_allocated_array_shape = {} + def __init__(self, writer): self.out = writer @@ -46,10 +48,26 @@ def printVar(self, ir): assert False, "Illegal state, codegenBase must have variable bitwidth info for VBW mode" else: self.out.printf("%s", ir.idf) - for e in ir.idx: + + if ir.idf in self.dynamic_allocated_array_shape and len(ir.idx)>0: + shape = self.dynamic_allocated_array_shape[ir.idf] self.out.printf('[') - self.print(e) - self.out.printf(']') + for i in range(len(ir.idx)): + self.print(ir.idx[i]) + + prod = 1 + for j in range(i+1, len(ir.idx)): + prod = prod*shape[j] + + if i!= len(ir.idx)-1: + self.out.printf('*' + str(prod) + ' + ') + + self.out.printf(']') + else: + for e in ir.idx: + self.out.printf('[') + self.print(e) + self.out.printf(']') def printBool(self, ir): self.out.printf({True: 'true', False: 'false'}[ir.b]) @@ -190,10 +208,10 @@ def printFuncCall(self, ir): x = -1 else: x = 0 - if x != 0: + if x != 0 and arg.idf not in self.dynamic_allocated_array_shape: self.out.printf("&") self.print(arg) - if x != 0 and x != -1: + if x != 0 and x != -1 and arg.idf not in self.dynamic_allocated_array_shape: self.out.printf("[0]" * x) if i != len(keys) - 1: self.out.printf(", ") diff --git a/Tools/SeeDot/seedot/compiler/codegen/x86.py b/Tools/SeeDot/seedot/compiler/codegen/x86.py index b37a73a2e..30ef9039d 100644 --- a/Tools/SeeDot/seedot/compiler/codegen/x86.py +++ b/Tools/SeeDot/seedot/compiler/codegen/x86.py @@ -191,7 +191,12 @@ def printVarDecls(self, globalVarDecl=True): shape_str = ''.join(['[' + str(n) + ']' for n in type.shape]) if not config.vbwEnabled: - self.out.printf('%s %s%s;\n', typ_str, idf_str, shape_str, indent=True) + if Type.isTensor(type): + self.dynamic_allocated_array_shape[idf_str] = type.shape + shape_prod_str = ('*'.join([str(n) for n in type.shape])) + self.out.printf('%s* %s = new %s[%s];\n', typ_str, idf_str, typ_str, shape_prod_str, indent=True) + else: + self.out.printf('%s %s%s;\n', typ_str, idf_str, shape_str, indent=True) if self.generateAllFiles: varsFile.printf('extern %s %s%s;\n', typ_str, idf_str, shape_str, indent=True) diff --git a/Tools/SeeDot/seedot/compiler/compiler.py b/Tools/SeeDot/seedot/compiler/compiler.py index 6cb31dedc..6f7652369 100644 --- a/Tools/SeeDot/seedot/compiler/compiler.py +++ b/Tools/SeeDot/seedot/compiler/compiler.py @@ -122,7 +122,7 @@ def genCodeWithFuncCalls(self, ast): compiler = irBuilder.IRBuilder(outputLog, self.intermediateScales, self.substitutions, self.scaleForX, self.variableToBitwidthMap, self.sparseMatrixSizes, self.demotedVarsList, self.demotedVarsOffsets) res = compiler.visit(ast) - + print(compiler.varScales) self.varScales = dict(compiler.varScales) diff --git a/Tools/SeeDot/seedot/compiler/converter/paramsBuilder.py b/Tools/SeeDot/seedot/compiler/converter/paramsBuilder.py index d1de91018..97987959d 100644 --- a/Tools/SeeDot/seedot/compiler/converter/paramsBuilder.py +++ b/Tools/SeeDot/seedot/compiler/converter/paramsBuilder.py @@ -48,7 +48,7 @@ def visitTransp(self, node: AST.Transp): def visitReshape(self, node: AST.Reshape): self.visit(node.expr) - def visitMaxpool(self, node: AST.Maxpool): + def visitPool(self, node: AST.Pool): self.visit(node.expr) def visitReverse(self, node: AST.Reverse): diff --git a/Tools/SeeDot/seedot/compiler/ir/irBuilder.py b/Tools/SeeDot/seedot/compiler/ir/irBuilder.py index c6135710c..4198104ec 100644 --- a/Tools/SeeDot/seedot/compiler/ir/irBuilder.py +++ b/Tools/SeeDot/seedot/compiler/ir/irBuilder.py @@ -386,7 +386,7 @@ def visitReshape(self, node: AST.Reshape): loopIters = [] if node.order == None: - node.order = [i+1 for i in range(type_in.dim)] + node.order = [i+1 for i in range(type_in.dim)] for order in node.order: order = order - 1 @@ -421,8 +421,8 @@ def visitReshape(self, node: AST.Reshape): return (prog_out, expr_out) - # out = maxpool(in, stride) - def visitMaxpool(self, node: AST.Maxpool): + # out = pool(in, stride) + def visitPool(self, node: AST.Pool): (prog_in, expr_in) = self.visit(node.expr) @@ -436,7 +436,7 @@ def visitMaxpool(self, node: AST.Maxpool): # Compute scaling factor #TODO - #Maxpool does NOT get profiled. So, it is not possible for the output variable to have a different scale + #pool does NOT get profiled. So, it is not possible for the output variable to have a different scale bw_in, scale_in = self.getBitwidthAndScale(expr_in.idf) bw_out, scale_out = bw_in, scale_in demote = 2 ** (scale_out - scale_in) @@ -455,16 +455,22 @@ def visitMaxpool(self, node: AST.Maxpool): self.demotedVarsOffsets[expr_out.idf] = 0 self.varsForBitwidth[expr_out.idf] = config.wordLength // 2 + poolFunctionName = "Maxpool" + if node.poolType == "avgpool": + poolFunctionName = "Avgpool" + comment = IR.Comment( - "maxpool(" + expr_in.idf + ", " + str(kernelSize) + ',' + str(padding) + ',' + str(stride) + ")") + poolFunctionName + "(" + expr_in.idf + ", " + str(kernelSize) + ',' + str(padding) + ',' + str(stride) + ")") - funcCall = IR.FuncCall("Maxpool", { + funcCall = IR.FuncCall(poolFunctionName, { expr_in: "A", expr_out: "B", IR.Int(N): "N", IR.Int(H): "H", IR.Int(W): "W", IR.Int(C): "C", + IR.Int(node.type.shape[1]): "outH", + IR.Int(node.type.shape[2]): "outW", IR.Int(kernelSize[0]): "FH", IR.Int(kernelSize[1]): "FW", IR.Int(stride[0]): "stideH", @@ -473,13 +479,15 @@ def visitMaxpool(self, node: AST.Maxpool): IR.Int(padding[1]): "HPADR", IR.Int(padding[2]): "WPADL", IR.Int(padding[3]): "WPADR" - }) if not self.vbwEnabled else IR.FuncCall("Maxpool"%(bw_in, bw_out), { + }) if not self.vbwEnabled else IR.FuncCall(poolFunctionName + ""%(bw_in, bw_out), { expr_in: "A", expr_out: "B", IR.Int(N): "N", IR.Int(H): "H", IR.Int(W): "W", IR.Int(C): "C", + IR.Int(node.type.shape[1]): "outH", + IR.Int(node.type.shape[2]): "outW", IR.Int(kernelSize[0]): "FH", IR.Int(kernelSize[1]): "FW", IR.Int(stride[0]): "stideH", @@ -494,9 +502,9 @@ def visitMaxpool(self, node: AST.Maxpool): self.counter_inst += 1 self.updateLiveRange([expr_in, expr_out]) - prog_maxpool = IR.Prog([comment, funcCall]) + prog_pool = IR.Prog([comment, funcCall]) - prog_out = IRUtil.concatPrograms(prog_in, prog_maxpool) + prog_out = IRUtil.concatPrograms(prog_in, prog_pool) # Update declarations self.varDeclarations[expr_out.idf] = type_out @@ -1888,12 +1896,10 @@ def visitBop2(self, node: AST.Bop2): # e : Tensor(), or Tensor(..) else: - assert type_out.dim == 2 or (type_out.dim == 4 and config.vbwEnabled), "Addition/subtraction of tensors is currently only supported for 2D tensors. Addition for 4D tensors is supported when VBW is enabled" - type_A = node.expr1.type type_B = node.expr2.type - assert (not type_out.dim == 4) or (type_A.dim == type_B.dim and expr_in_A.idf not in self.globalVars and expr_in_B.idf not in self.globalVars and node.op == SeeDotParser.ADD), "For 4D operation, no broadcasting supported, inputs should not be model parameters, and operation cannot be subtraction" + assert type_out.dim == 2 or type_out.dim == 4, "Addition/subtraction of tensors is currently only supported for 2D/4D tensors" c = '' if op_fn == operator.add: @@ -2008,8 +2014,8 @@ def visitBop2(self, node: AST.Bop2): if type_out.dim == 2: profile = IR.FuncCall("Profile2", { expr_out: "Var", - IR.Int(I): "I", - IR.Int(J): "J", + IR.Int(type_out.shape[0]): "I", + IR.Int(type_out.shape[1]): "J", IR.String(expr_out): "VarName" }) elif type_out.dim == 4: diff --git a/Tools/SeeDot/seedot/compiler/type.py b/Tools/SeeDot/seedot/compiler/type.py index cf309710f..1600a9708 100644 --- a/Tools/SeeDot/seedot/compiler/type.py +++ b/Tools/SeeDot/seedot/compiler/type.py @@ -144,7 +144,7 @@ def visitReshape(self, node: ast.Reshape): return node.type # Reduces the shape of a tensor by choosing the maximum from a filter - def visitMaxpool(self, node: ast.Maxpool): + def visitPool(self, node: ast.Pool): node.expr.gamma = dict(node.gamma) exprType = self.visit(node.expr) @@ -160,8 +160,6 @@ def visitMaxpool(self, node: ast.Maxpool): WPADL = node.padding[2] WPADR = node.padding[3] - assert HPADL == HPADR == WPADL == WPADR == 0, "Non zero paddings not supported currently" - outH = ((H + HPADL + HPADR - FH)//node.stride[0]) + 1 outW = ((W + WPADL + WPADR - FW)//node.stride[1]) + 1 diff --git a/Tools/SeeDot/seedot/config.py b/Tools/SeeDot/seedot/config.py index 2518513fb..37731c0c8 100644 --- a/Tools/SeeDot/seedot/config.py +++ b/Tools/SeeDot/seedot/config.py @@ -29,12 +29,13 @@ fixedPointVbwIteration = False -class MaximisingMetric: +class Metric: accuracy = "acc" disagreements = "disagree" reducedDisagreements = "red_disagree" + regressionLoss = "reg_loss" default = [accuracy] - all = [accuracy, disagreements, reducedDisagreements] + all = [accuracy, disagreements, reducedDisagreements, regressionLoss] class Algo: bonsai = "bonsai" @@ -43,9 +44,11 @@ class Algo: rnn = "rnn" rnnpool = "rnnpool" mbconv = "mbconv" + resnet18 = "resnet-18" + resnet50 = "resnet-50" test = "test" default = [bonsai, protonn] - all = [bonsai, lenet, protonn, rnn, rnnpool, mbconv, test] + all = [bonsai, lenet, protonn, rnn, rnnpool, mbconv, resnet18, resnet50, test] class Version: diff --git a/Tools/SeeDot/seedot/main.py b/Tools/SeeDot/seedot/main.py index 758acb44d..80cc56ab7 100644 --- a/Tools/SeeDot/seedot/main.py +++ b/Tools/SeeDot/seedot/main.py @@ -21,13 +21,13 @@ class Main: - def __init__(self, algo, version, target, trainingFile, testingFile, modelDir, sf, maximisingMetric, dataset, numOutputs, source): + def __init__(self, algo, version, target, trainingFile, testingFile, modelDir, sf, metric, dataset, numOutputs, source): self.algo, self.version, self.target = algo, version, target self.trainingFile, self.testingFile, self.modelDir = trainingFile, testingFile, modelDir self.sf = sf self.dataset = dataset self.accuracy = {} - self.maximisingMetric = maximisingMetric + self.metric = metric self.numOutputs = numOutputs self.source = source self.variableSubstitutions = {} #evaluated during profiling code run @@ -205,12 +205,12 @@ def runAll(self, version, datasetType, codeIdToScaleFactorMap, demotedVarsToOffs file.write("\nAccuracy at scale factor %d is %.3f%%, Disagreement Count is %d, Reduced Disagreement Count is %d\n" % (sf, execMap[str(codeId)][0], execMap[str(codeId)][1], execMap[str(codeId)][2])) file.close() else: - def getMaximisingMetricValue(a): - if self.maximisingMetric == config.MaximisingMetric.accuracy: + def getMetricValue(a): + if self.metric == config.Metric.accuracy: return (a[1][0], -a[1][1], -a[1][2]) - elif self.maximisingMetric == config.MaximisingMetric.disagreements: + elif self.metric == config.Metric.disagreements: return (-a[1][1], -a[1][2], a[1][0]) - elif self.maximisingMetric == config.MaximisingMetric.reducedDisagreements: + elif self.metric == config.Metric.reducedDisagreements: return (-a[1][2], -a[1][1], a[1][0]) allVars = [] for demotedVars in demotedVarsToOffsetToCodeId: @@ -218,14 +218,14 @@ def getMaximisingMetricValue(a): print("Demoted vars: %s\n" % str(demotedVars)) x = [(i, execMap[str(offsetToCodeId[i])]) for i in offsetToCodeId] - x.sort(key=getMaximisingMetricValue, reverse=True) + x.sort(key=getMetricValue, reverse=True) allVars.append(((demotedVars, x[0][0]), x[0][1])) for offset in offsetToCodeId: codeId = offsetToCodeId[offset] print("Offset %d (Code ID %d): Accuracy %.3f%%, Disagreement Count %d, Reduced Disagreement Count %d\n" %(offset, codeId, execMap[str(codeId)][0], execMap[str(codeId)][1], execMap[str(codeId)][2])) if not doNotSort: - allVars.sort(key=getMaximisingMetricValue, reverse=True) + allVars.sort(key=getMetricValue, reverse=True) self.varDemoteDetails = allVars return True, False @@ -408,19 +408,19 @@ def performSearch(self): # Reverse sort the accuracies, print the top 5 accuracies and return the # best scaling factor def getBestScale(self): - def getMaximisingMetricValue(a): - if self.maximisingMetric == config.MaximisingMetric.accuracy: + def getMetricValue(a): + if self.metric == config.Metric.accuracy: return (a[1][0], -a[1][1], -a[1][2]) if not config.higherOffsetBias else (a[1][0], -a[0]) - elif self.maximisingMetric == config.MaximisingMetric.disagreements: + elif self.metric == config.Metric.disagreements: return (-a[1][1], -a[1][2], a[1][0]) if not config.higherOffsetBias else (-max(5, a[1][1]), -a[0]) - elif self.maximisingMetric == config.MaximisingMetric.reducedDisagreements: + elif self.metric == config.Metric.reducedDisagreements: return (-a[1][2], -a[1][1], a[1][0]) if not config.higherOffsetBias else (-max(5, a[1][2]), -a[0]) - elif self.algo == config.Algo.test: + elif self.metric == config.Metric.regressionLoss: # minimize regression error return (-a[1][0]) x = [(i, self.accuracy[i]) for i in self.accuracy] - x.sort(key=getMaximisingMetricValue, reverse=True) + x.sort(key=getMetricValue, reverse=True) sorted_accuracy = x[:5] print(sorted_accuracy) return sorted_accuracy[0][0] diff --git a/Tools/SeeDot/test/test.py b/Tools/SeeDot/test/test.py index f610d9fab..9198fa76c 100644 --- a/Tools/SeeDot/test/test.py +++ b/Tools/SeeDot/test/test.py @@ -90,7 +90,7 @@ def check_result(self, graph, name, output_shape): # need to create random input and output input_dims = common.proto_val_to_dimension_tuple(model.graph.input[0]) - inp = self._get_rnd_float32(shape=input_dims, get_np_array=True) + inp = self._get_rnd_float32(shape=input_dims, get_np_array=True, low=0, high=256) op = self.get_onnx_output(model_path, inp) # print(type(inp), type(op)) @@ -118,7 +118,7 @@ def check_result(self, graph, name, output_shape): config.vbwEnabled = False obj = main.Main(config.Algo.test, config.Version.fixed, config.Target.x86, training_input, testing_input, - 'model', None, None, None, self.get_list_prod(output_shape), config.Source.onnx) + 'model', None, config.Metric.regressionLoss , None, self.get_list_prod(output_shape), config.Source.onnx) obj.run() def test_relu(self): @@ -144,13 +144,11 @@ def test_relu(self): ) self.check_result(graph, name, output_shape) - # TODO: Fix maxpool - # currently only support 0 padding and stride[2,2] - # does not even work with strides = [1,1] + # TODO: padding -inf vs 0 in case of maxpool? def test_maxpool(self): name = "maxpool" input_shape = [1, 1, 6, 6] - output_shape = [1, 1, 3, 3] + output_shape = [1, 1, 5, 5] X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [self.get_list_prod(input_shape), 1]) @@ -160,7 +158,7 @@ def test_maxpool(self): state_out = helper.make_tensor_value_info('state_out', TensorProto.FLOAT, output_shape) - node_def = helper.make_node("MaxPool", ['state_in'], ['state_out'], kernel_shape=[2, 2], strides=[2,2]) + node_def = helper.make_node("MaxPool", ['state_in'], ['state_out'], kernel_shape=[2, 2], strides=[1,1]) graph = helper.make_graph( [reshape_node, node_def], name, @@ -170,11 +168,36 @@ def test_maxpool(self): ) self.check_result(graph, name, output_shape) + # sometimes the sum overflows + # TODO: replace int32 instead of MYINT for sum + def test_avgpool(self): + name = "maxpool" + input_shape = [1, 1, 6, 6] + output_shape = [1, 1, 1, 1] + + X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [self.get_list_prod(input_shape), 1]) + + shape_param = helper.make_tensor('shape_param', TensorProto.INT64, [4], input_shape) + + reshape_node = helper.make_node("Reshape", ['X', 'shape_param'], ['state_in']) + + state_out = helper.make_tensor_value_info('state_out', + TensorProto.FLOAT, output_shape) + node_def = helper.make_node("GlobalAveragePool", ['state_in'], ['state_out']) + graph = helper.make_graph( + [reshape_node, node_def], + name, + [X], + [state_out], + [shape_param] + ) + self.check_result(graph, name, output_shape) + # TODO: with group!=1 def test_conv2d(self): name = "conv2d" - input_shape = [1, 3, 10, 10] - output_shape = [1, 6, 5, 5] + input_shape = [1, 3, 224, 224] + output_shape = [1, 64, 112, 112] X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [self.get_list_prod(input_shape), 1]) @@ -185,9 +208,9 @@ def test_conv2d(self): state_out = helper.make_tensor_value_info('state_out', TensorProto.FLOAT, output_shape) node_def = helper.make_node("Conv", ['state_in', 'weight'], ['state_out'], - pads=[1, 1, 1, 1], strides=[2, 2], kernel_shape=[3, 3], group=1) + pads=[3, 3, 3, 3], strides=[2, 2], kernel_shape=[7, 7], group=1) - weight_shape = [6, 3, 3, 3] + weight_shape = [64, 3, 7, 7] weight_val = self._get_rnd_float32(shape=weight_shape) weight = helper.make_tensor('weight', TensorProto.FLOAT, weight_shape, weight_val) @@ -201,161 +224,51 @@ def test_conv2d(self): ) self.check_result(graph, name, output_shape) - # def test_pad(self): - # name = "pad" - # state_in = helper.make_tensor_value_info('state_in', TensorProto.FLOAT, [1, 3, 10, 10]) - # pads = helper.make_tensor_value_info('pads', TensorProto.INT64, [8]) - # pad_init = numpy_helper.from_array(np.array([0,0,1,1,0,0,1,1], dtype=int), name='pads') - # const_val = helper.make_tensor_value_info('const_val', TensorProto.FLOAT, [1]) - # const_val_init = numpy_helper.from_array(np.array([0.0], dtype=np.float32), name='const_val') - # state_out = helper.make_tensor_value_info('state_out', TensorProto.FLOAT, [1,3,12,12]) - # node_def = helper.make_node("Pad", ['state_in', 'pads', 'const_val'], ['state_out'], mode="constant") - # graph = helper.make_graph([node_def],name,[state_in, pads, const_val],[state_out],initializer=[pad_init, const_val_init]) - # self.check_result(graph, name) - - - # def test_relu3d(self): - # name = "relu3d" - # state_in = helper.make_tensor_value_info('state_in', - # TensorProto.FLOAT, [1, 3, 7, 7, 7]) - # state_out = helper.make_tensor_value_info('state_out', - # TensorProto.FLOAT, [1, 3, 7, 7, 7]) - # node_def = helper.make_node("Relu", ['state_in'], ['state_out']) - # graph = helper.make_graph( - # [node_def], - # name, - # [state_in], - # [state_out], - # [] - # ) - # self.check_result(graph, name) - - # def test_reducemean(self): - # name = "reducemean" - # state_in = helper.make_tensor_value_info('state_in', - # TensorProto.FLOAT, [1, 1024, 7, 7]) - # state_out = helper.make_tensor_value_info('state_out', - # TensorProto.FLOAT, [1, 1024]) - # node_def = helper.make_node("ReduceMean", ['state_in'], ['state_out'], axes=[2,3], keepdims=0) - # graph = helper.make_graph( - # [node_def], - # name, - # [state_in], - # [state_out], - # [] - # ) - # self.check_result(graph, name) - - # def test_batchnormalization(self): - # name = "batchnormalization" - # state_in = helper.make_tensor_value_info('state_in', - # TensorProto.FLOAT, [1, 24, 10, 10]) - # state_out = helper.make_tensor_value_info('state_out', - # TensorProto.FLOAT, [1, 24, 10, 10]) - # node_def = helper.make_node("BatchNormalization", ['state_in', 'weight', 'bias','mean','var'], ['state_out'], - # momentum=0.8999999761581421) - - # weight_shape = [24] - # weight_val = self._get_rnd_float32(shape=weight_shape) - # weight = helper.make_tensor('weight', TensorProto.FLOAT, weight_shape, weight_val) - - # bias_shape = [24] - # bias_val = self._get_rnd_float32(shape=weight_shape) - # bias = helper.make_tensor('bias', TensorProto.FLOAT, bias_shape, bias_val) - - # mean_shape = [24] - # mean_val = self._get_rnd_float32(shape=weight_shape) - # mean = helper.make_tensor('mean', TensorProto.FLOAT, mean_shape, mean_val) - - - # var_shape = [24] - # var_val = self._get_rnd_float32(shape=weight_shape, low=0, high=1) - # var = helper.make_tensor('var', TensorProto.FLOAT, var_shape, var_val) - - # graph = helper.make_graph( - # [node_def], - # name, - # [state_in], - # [state_out], - # [weight, bias, mean, var] - # ) - # self.check_result(graph, name) - - # def test_conv3d(self): - # name = "conv3d" - # state_in = helper.make_tensor_value_info('state_in',TensorProto.FLOAT, [1, 2, 64, 256, 256]) - # state_out = helper.make_tensor_value_info('state_out', - # TensorProto.FLOAT, [1, 2, 64, 256, 256]) - # node_def = helper.make_node("Conv", ['state_in', 'weight'], ['state_out'], - # pads=[1, 1, 1, 1, 1, 1], strides=[1, 1, 1], kernel_shape=[3, 3, 3]) - - # weight_shape = [2, 2, 3, 3, 3] - # weight_val = self._get_rnd_float32(shape=weight_shape) - # np.save('weight', weight_val) - - # weight = helper.make_tensor('weight', TensorProto.FLOAT, weight_shape, weight_val) - - # graph = helper.make_graph( - # [node_def], - # name, - # [state_in], - # [state_out], - # [weight] - # ) - # self.check_result(graph, name) - - # def test_conv_transpose(self): - # name = "conv_transpose" - # state_in = helper.make_tensor_value_info('state_in', - # TensorProto.FLOAT, [1, 3, 10, 10]) - # state_out = helper.make_tensor_value_info('state_out', - # TensorProto.FLOAT, [1, 5, 19, 19]) - # node_def = helper.make_node("ConvTranspose", ['state_in', 'weight'], ['state_out'], - # pads=[1, 1, 1, 1], strides=[2, 2], kernel_shape=[3, 3]) - - # weight_shape = [3, 5, 3, 3] - # weight_val = self._get_rnd_float32(shape=weight_shape) - - # weight = helper.make_tensor('weight', TensorProto.FLOAT, weight_shape, weight_val) - - # graph = helper.make_graph( - # [node_def], - # name, - # [state_in], - # [state_out], - # [weight] - # ) - - # self.check_result(graph, name) - - # # For this to run onnx_run_tf.py should be used in the compile script - # # since onnxruntime does not support convtranspose3d - # def test_conv_transpose3d(self): - # name = "conv3dTranspose" - # state_in = helper.make_tensor_value_info('state_in', - # TensorProto.FLOAT, [1, 3, 10, 10, 10]) - # state_out = helper.make_tensor_value_info('state_out', - # TensorProto.FLOAT, [1, 5, 19, 19, 19]) - # node_def = helper.make_node("ConvTranspose", ['state_in', 'weight', 'bias'], ['state_out'], - # # check with pads which are not 1 - # pads=[1, 1, 1, 1, 1, 1], strides=[2, 2, 2], kernel_shape=[3, 3, 3]) - - # weight_shape = [3, 5, 3, 3, 3] - # weight_val = self._get_rnd_float32(shape=weight_shape) - # bias_shape = [5] - # bias_val = self._get_rnd_float32(shape=bias_shape) - - # weight = helper.make_tensor('weight', TensorProto.FLOAT, weight_shape, weight_val) - # bias = helper.make_tensor('bias', TensorProto.FLOAT, bias_shape, bias_val) - - # graph = helper.make_graph( - # [node_def], - # name, - # [state_in], - # [state_out], - # [weight, bias] - # ) - # self.check_result(graph, name) + def test_bn(self): + name = "batchnormalization" + input_shape = [1, 2, 3, 3] + output_shape = [1, 2, 3, 3] + + X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [self.get_list_prod(input_shape), 1]) + + shape_param = helper.make_tensor('shape_param', TensorProto.INT64, [4], input_shape) + + reshape_node = helper.make_node("Reshape", ['X', 'shape_param'], ['state_in']) + + state_out = helper.make_tensor_value_info('state_out', + TensorProto.FLOAT, output_shape) + + node_def = helper.make_node("BatchNormalization", ['state_in', 'weight', 'bias','mean','var'], ['state_out'], + momentum=0.8999999761581421) + + weight_shape = [2] + weight_val = self._get_rnd_float32(shape=weight_shape) + weight = helper.make_tensor('weight', TensorProto.FLOAT, weight_shape, weight_val) + + bias_shape = [2] + # bias_val = [1e-5,1e-5] + bias_val = self._get_rnd_float32(shape=weight_shape) + bias = helper.make_tensor('bias', TensorProto.FLOAT, bias_shape, bias_val) + + mean_shape = [2] + # mean_val = [1e-5,1e-5] + mean_val = self._get_rnd_float32(shape=weight_shape) + mean = helper.make_tensor('mean', TensorProto.FLOAT, mean_shape, mean_val) + + + var_shape = [2] + # var_val = [1,1] + var_val = self._get_rnd_float32(shape=weight_shape, low=0, high=1) + var = helper.make_tensor('var', TensorProto.FLOAT, var_shape, var_val) + + graph = helper.make_graph( + [reshape_node, node_def], + name, + [X], + [state_out], + [shape_param, weight, bias, mean, var] + ) + self.check_result(graph, name, output_shape) if __name__ == '__main__': unittest.main()