ncnn importer (#332)

* ncnn importer

* convert convolution and convolutiondepthwise

* convert innerproduct

* pooling and softmax

* mobilenetv1 runs

* concat and split, squeezenet runs

* add ncnn_ops doc

* apply code-format changes

* Update convolution.cpp

* Update CMakeLists.txt

* Fix build errors on macos

* Fix build errors on macos

* Add first ncnn test

* Fix type hints

* Fix tests folder name

* clip hardsigmoid hardswish sigmoid

* Fix pooling

* Fix test

* Add import ncnn api

* Add more ops

* Pass test

* Remove unused code

* Fix code format

* Fix build

* Fix build

---------

Co-authored-by: nihui <nihui@users.noreply.github.com>
Co-authored-by: sunnycase <sunnycase@live.cn>
pull/1096/head
nihui 2023-09-19 16:28:19 +08:00 committed by GitHub
parent c8d94d07ff
commit 77be775f6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 2092 additions and 1532 deletions

View File

@ -2,11 +2,20 @@ name: code-format
on: [pull_request]
concurrency:
group: code-format-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
code-format:
permissions:
contents: write # for stefanzweifel/git-auto-commit-action to push code in repo
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v1

View File

@ -261,6 +261,7 @@ jobs:
dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/tflite_basic.xml pytest tests/importer/tflite_/basic/ --doctest-modules --junitxml=test_results/tflite_basic.xml
dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/tflite_combine.xml pytest tests/importer/tflite_/combine/ --doctest-modules --junitxml=test_results/tflite_combine.xml
dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/tflite_model.xml pytest tests/importer/tflite_/model/ --doctest-modules --junitxml=test_results/tflite_model.xml
dotnet-coverage collect -s tools/dotnet_coverage.settings.xml -f cobertura -o coverage/ncnn_basic.xml pytest tests/importer/ncnn_/basic/ --doctest-modules --junitxml=test_results/ncnn_basic.xml
dotnet-coverage merge -o coverage.integration.xml -f cobertura -r coverage/*.xml
- name: Upload Coverage

3
.gitignore vendored
View File

@ -262,6 +262,9 @@ __pycache__/
# vscode
.vscode/
# clangd
.cache/
# pip
/python/*/dist
*egg-info

View File

@ -49,7 +49,7 @@
<PackageVersion Include="OrtKISharp" Version="0.0.2" />
<PackageVersion Include="RazorLight" Version="2.3.0" />
<PackageVersion Include="Singulink.Collections.Weak" Version="1.0.2" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.435" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.507" />
<PackageVersion Include="System.CommandLine.Hosting" Version="0.3.0-alpha.21216.1" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Reactive" Version="5.0.0" />

19
docs/ncnn_ops.md Normal file
View File

@ -0,0 +1,19 @@
## Supported ncnn ops
## 支持的 ncnn 算子
| Operator | Is Supported |
|-------|------------------ |
| Input | ✅ |
| Clip | ✅ |
| Concat | ✅ |
| Convolution | ✅ |
| ConvolutionDepthWise | ✅ |
| HardSigmoid | ✅ |
| HardSwish | ✅ |
| Innerproduct | ✅ |
| Pooling | ✅ |
| ReLU | ✅ |
| Sigmoid | ✅ |
| Softmax | ✅ |
| Split | ✅ |

View File

@ -0,0 +1,33 @@
7767517
31 31
Input data 0 1 data -23330=4,3,224,224,3 0=224 1=224 2=3
Convolution conv1 1 1 data conv1_relu1 -23330=4,3,112,112,32 0=32 1=3 3=2 4=1 5=1 6=864 9=1
ConvolutionDepthWise conv2_1/dw 1 1 conv1_relu1 conv2_1/dw_relu2_1/dw -23330=4,3,112,112,32 0=32 1=3 4=1 5=1 6=288 7=32 9=1
Convolution conv2_1/sep 1 1 conv2_1/dw_relu2_1/dw conv2_1/sep_relu2_1/sep -23330=4,3,112,112,64 0=64 1=1 5=1 6=2048 9=1
ConvolutionDepthWise conv2_2/dw 1 1 conv2_1/sep_relu2_1/sep conv2_2/dw_relu2_2/dw -23330=4,3,56,56,64 0=64 1=3 3=2 4=1 5=1 6=576 7=64 9=1
Convolution conv2_2/sep 1 1 conv2_2/dw_relu2_2/dw conv2_2/sep_relu2_2/sep -23330=4,3,56,56,128 0=128 1=1 5=1 6=8192 9=1
ConvolutionDepthWise conv3_1/dw 1 1 conv2_2/sep_relu2_2/sep conv3_1/dw_relu3_1/dw -23330=4,3,56,56,128 0=128 1=3 4=1 5=1 6=1152 7=128 9=1
Convolution conv3_1/sep 1 1 conv3_1/dw_relu3_1/dw conv3_1/sep_relu3_1/sep -23330=4,3,56,56,128 0=128 1=1 5=1 6=16384 9=1
ConvolutionDepthWise conv3_2/dw 1 1 conv3_1/sep_relu3_1/sep conv3_2/dw_relu3_2/dw -23330=4,3,28,28,128 0=128 1=3 3=2 4=1 5=1 6=1152 7=128 9=1
Convolution conv3_2/sep 1 1 conv3_2/dw_relu3_2/dw conv3_2/sep_relu3_2/sep -23330=4,3,28,28,256 0=256 1=1 5=1 6=32768 9=1
ConvolutionDepthWise conv4_1/dw 1 1 conv3_2/sep_relu3_2/sep conv4_1/dw_relu4_1/dw -23330=4,3,28,28,256 0=256 1=3 4=1 5=1 6=2304 7=256 9=1
Convolution conv4_1/sep 1 1 conv4_1/dw_relu4_1/dw conv4_1/sep_relu4_1/sep -23330=4,3,28,28,256 0=256 1=1 5=1 6=65536 9=1
ConvolutionDepthWise conv4_2/dw 1 1 conv4_1/sep_relu4_1/sep conv4_2/dw_relu4_2/dw -23330=4,3,14,14,256 0=256 1=3 3=2 4=1 5=1 6=2304 7=256 9=1
Convolution conv4_2/sep 1 1 conv4_2/dw_relu4_2/dw conv4_2/sep_relu4_2/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=131072 9=1
ConvolutionDepthWise conv5_1/dw 1 1 conv4_2/sep_relu4_2/sep conv5_1/dw_relu5_1/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1
Convolution conv5_1/sep 1 1 conv5_1/dw_relu5_1/dw conv5_1/sep_relu5_1/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1
ConvolutionDepthWise conv5_2/dw 1 1 conv5_1/sep_relu5_1/sep conv5_2/dw_relu5_2/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1
Convolution conv5_2/sep 1 1 conv5_2/dw_relu5_2/dw conv5_2/sep_relu5_2/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1
ConvolutionDepthWise conv5_3/dw 1 1 conv5_2/sep_relu5_2/sep conv5_3/dw_relu5_3/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1
Convolution conv5_3/sep 1 1 conv5_3/dw_relu5_3/dw conv5_3/sep_relu5_3/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1
ConvolutionDepthWise conv5_4/dw 1 1 conv5_3/sep_relu5_3/sep conv5_4/dw_relu5_4/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1
Convolution conv5_4/sep 1 1 conv5_4/dw_relu5_4/dw conv5_4/sep_relu5_4/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1
ConvolutionDepthWise conv5_5/dw 1 1 conv5_4/sep_relu5_4/sep conv5_5/dw_relu5_5/dw -23330=4,3,14,14,512 0=512 1=3 4=1 5=1 6=4608 7=512 9=1
Convolution conv5_5/sep 1 1 conv5_5/dw_relu5_5/dw conv5_5/sep_relu5_5/sep -23330=4,3,14,14,512 0=512 1=1 5=1 6=262144 9=1
ConvolutionDepthWise conv5_6/dw 1 1 conv5_5/sep_relu5_5/sep conv5_6/dw_relu5_6/dw -23330=4,3,7,7,512 0=512 1=3 3=2 4=1 5=1 6=4608 7=512 9=1
Convolution conv5_6/sep 1 1 conv5_6/dw_relu5_6/dw conv5_6/sep_relu5_6/sep -23330=4,3,7,7,1024 0=1024 1=1 5=1 6=524288 9=1
ConvolutionDepthWise conv6/dw 1 1 conv5_6/sep_relu5_6/sep conv6/dw_relu6/dw -23330=4,3,7,7,1024 0=1024 1=3 4=1 5=1 6=9216 7=1024 9=1
Convolution conv6/sep 1 1 conv6/dw_relu6/dw conv6/sep_relu6/sep -23330=4,3,7,7,1024 0=1024 1=1 5=1 6=1048576 9=1
Pooling pool6 1 1 conv6/sep_relu6/sep pool6 -23330=4,1,1024,1,1 0=1 4=1
InnerProduct fc7 1 1 pool6 fc7 -23330=4,1,1000,1,1 0=1000 1=1 2=1024000
Softmax prob 1 1 fc7 output -23330=4,1,1000,1,1

View File

@ -4,11 +4,11 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Google.OrTools.runtime.linux-arm64": {
@ -103,8 +103,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -186,11 +186,15 @@ class Compiler:
def import_onnx(self, model_content: bytes, options: ImportOptions) -> None:
self._compile_options.input_format = "onnx"
self._import_module(model_content)
self._import_onnx_module(model_content)
def import_tflite(self, model_content: bytes, options: ImportOptions) -> None:
self._compile_options.input_format = "tflite"
self._import_module(model_content)
self._import_tflite_module(model_content)
def import_ncnn(self, model_param: bytes, model_bin : bytes, options: ImportOptions) -> None:
self._compile_options.input_format = "ncnn"
self._import_ncnn_module(model_param, model_bin)
def use_ptq(self, ptq_dataset_options: PTQTensorOptions) -> None:
dataset = [_nncase.RTValue.from_runtime_tensor(
@ -275,9 +279,18 @@ class Compiler:
self._compile_options.dump_flags = dump_flags
self._compile_options.dump_dir = compile_options.dump_dir
def _import_module(self, model_content: bytes | io.RawIOBase) -> None:
def _import_onnx_module(self, model_content: bytes | io.RawIOBase) -> None:
stream = io.BytesIO(model_content) if isinstance(model_content, bytes) else model_content
self._module = IRModule(self._compiler.import_module(stream))
self._module = IRModule(self._compiler.import_onnx_module(stream))
def _import_tflite_module(self, model_content: bytes | io.RawIOBase) -> None:
stream = io.BytesIO(model_content) if isinstance(model_content, bytes) else model_content
self._module = IRModule(self._compiler.import_tflite_module(stream))
def _import_ncnn_module(self, model_param: bytes | io.RawIOBase, model_bin: bytes | io.RawIOBase) -> None:
param_stream = io.BytesIO(model_param) if isinstance(model_param, bytes) else model_param
bin_stream = io.BytesIO(model_bin) if isinstance(model_bin, bytes) else model_bin
self._module = IRModule(self._compiler.import_ncnn_module(param_stream, bin_stream))
def check_target(target: str):

View File

@ -299,7 +299,9 @@ PYBIND11_MODULE(_nncase, m) {
.def_property_readonly("entry", &ir_module::entry);
py::class_<compiler>(m, "Compiler")
.def("import_module", &compiler::import_module)
.def("import_tflite_module", &compiler::import_tflite_module)
.def("import_onnx_module", &compiler::import_onnx_module)
.def("import_ncnn_module", &compiler::import_ncnn_module)
.def("compile", &compiler::compile)
.def("gencode", &compiler::gencode);

View File

@ -6,6 +6,7 @@ onnx==1.12.0
onnx-simplifier==0.3.6
onnxoptimizer==0.2.6
onnxruntime==1.12.0
ncnn==1.0.20230816
numpy==1.21.0
torch==1.9.0
torchvision==0.10.0
@ -15,8 +16,6 @@ kendryte-caffe
pytest
pytest-xdist
pyyaml
pythonnet==3.0.1
clr_loader==0.2.4
toml==0.10.2
pandas
tabulate

View File

@ -159,8 +159,13 @@ typedef struct {
clr_object_handle_t (*compile_session_get_compiler)(
clr_object_handle_t compile_session);
void (*compiler_initialize)();
clr_object_handle_t (*compiler_import_module)(clr_object_handle_t compiler,
clr_object_handle_t stream);
clr_object_handle_t (*compiler_import_tflite_module)(
clr_object_handle_t compiler, clr_object_handle_t stream);
clr_object_handle_t (*compiler_import_onnx_module)(
clr_object_handle_t compiler, clr_object_handle_t stream);
clr_object_handle_t (*compiler_import_ncnn_module)(
clr_object_handle_t compiler, clr_object_handle_t param_stream,
clr_object_handle_t bin_stream);
void (*compiler_compile)(clr_object_handle_t compiler);
void (*compiler_gencode)(clr_object_handle_t compiler,
clr_object_handle_t stream);
@ -642,9 +647,20 @@ class compiler : public clr_object_base {
public:
using clr_object_base::clr_object_base;
ir_module import_module(cstream &stream) {
ir_module import_tflite_module(cstream &stream) {
return {std::in_place, nncase_clr_api()->compiler_import_tflite_module(
get(), stream.get())};
}
ir_module import_onnx_module(cstream &stream) {
return {std::in_place, nncase_clr_api()->compiler_import_onnx_module(
get(), stream.get())};
}
ir_module import_ncnn_module(cstream &param_stream, cstream &bin_stream) {
return {std::in_place,
nncase_clr_api()->compiler_import_module(get(), stream.get())};
nncase_clr_api()->compiler_import_ncnn_module(
get(), param_stream.get(), bin_stream.get())};
}
void compile() { nncase_clr_api()->compiler_compile(obj_.get()); }

View File

@ -86,6 +86,10 @@ public sealed class Compile : Command
alias: "--calib-method",
description: $"model quant options, default is {Quantization.CalibMethod.Kld}",
getDefaultValue: () => Quantization.CalibMethod.Kld));
AddOption(new Option<bool>(
alias: "--benchmark-only",
description: $"benchmark only",
getDefaultValue: () => false));
Handler = CommandHandler.Create<CliCompileOptions, IHost>(RunAsync);
}
@ -138,17 +142,14 @@ public sealed class Compile : Command
},
ModelQuantMode = cliOptions.ModelQuantMode,
},
IsBenchmarkOnly = cliOptions.BenchmarkOnly,
};
// 2. import the model
var target = CompilerServices.GetTarget(cliOptions.Target);
using var compileSession = CompileSession.Create(target, compileOptions);
var compiler = compileSession.Compiler;
IRModule module;
using (var model_stream = File.OpenRead(compileOptions.InputFile))
{
module = await compiler.ImportModuleAsync(model_stream);
}
var module = await compiler.ImportModuleAsync(compileOptions.InputFormat, compileOptions.InputFile, compileOptions.IsBenchmarkOnly);
// 3. create the calib dataset
if (compileOptions.QuantizeOptions.ModelQuantMode == Quantization.ModelQuantMode.UsePTQ)
@ -206,6 +207,8 @@ internal sealed class CliCompileOptions
public string Dataset { get; set; }
public DatasetFormat DatasetFormat { get; set; }
public bool BenchmarkOnly { get; set; }
}
#pragma warning restore CS8618

View File

@ -33,11 +33,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"System.CommandLine.Hosting": {
@ -344,8 +344,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -10,11 +10,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
@ -53,8 +53,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -48,27 +48,22 @@ internal class Compiler : ICompiler
/// <inheritdoc/>
public void ImportIRModule(IRModule module) => _module = module;
public async Task<IRModule> ImportModuleAsync(Stream content)
public Task<IRModule> ImportTFLiteModuleAsync(Stream content)
{
var module = ImportModel(content);
if (_dumpper.IsEnabled(DumpFlags.Compile))
{
_dumpper.DumpModule(module, "IRImport");
}
var module = Importers.ImportTFLite(content, _compileSession);
return InitializeModuleAsync(module);
}
var preprocess_option = _compileSession.CompileOptions;
public Task<IRModule> ImportOnnxModuleAsync(Stream content)
{
var module = Importers.ImportOnnx(content, _compileSession);
return InitializeModuleAsync(module);
}
await RunPassAsync(pmg => BroadcastOutputNamesAfterImportPass(pmg), "BroadcastOutputNamesAfterImport");
await RunPassAsync(pmg => pmg.Add<ShapeInferPass>(), "ShapeInferAfterImport");
await RunPassAsync(pmg => AddPreAndPostProcess(pmg), "AddPreAndPostProcessAfterImport");
var inferSucc = CompilerServices.InferenceType(module.Entry!);
if (!inferSucc)
{
throw new InvalidOperationException("InferShape Failed For This Model!");
}
return module;
public Task<IRModule> ImportNcnnModuleAsync(Stream ncnnParam, Stream ncnnBin)
{
var module = Importers.ImportNcnn(ncnnParam, ncnnBin, _compileSession);
return InitializeModuleAsync(module);
}
public void BroadcastOutputNamesAfterImportPass(IPassManager passManager)
@ -277,6 +272,30 @@ internal class Compiler : ICompiler
linkedModel.Serialize(output);
}
private async Task<IRModule> InitializeModuleAsync(IRModule module)
{
_module = module;
if (_dumpper.IsEnabled(DumpFlags.Compile))
{
_dumpper.DumpModule(module, "IRImport");
}
var preprocess_option = _compileSession.CompileOptions;
await RunPassAsync(pmg => BroadcastOutputNamesAfterImportPass(pmg), "BroadcastOutputNamesAfterImport");
await RunPassAsync(pmg => pmg.Add<ShapeInferPass>(), "ShapeInferAfterImport");
await RunPassAsync(pmg => AddPreAndPostProcess(pmg), "AddPreAndPostProcessAfterImport");
var inferSucc = CompilerServices.InferenceType(module.Entry!);
if (!inferSucc)
{
throw new InvalidOperationException("InferShape Failed For This Model!");
}
return module;
}
private void RegisterTargetIndependQuantPass(IPassManager passManager)
{
var quantMode = _compileSession.CompileOptions.QuantizeOptions.ModelQuantMode;
@ -290,17 +309,6 @@ internal class Compiler : ICompiler
}
}
private IRModule ImportModel(Stream content)
{
_module = _compileSession.CompileOptions.InputFormat switch
{
"tflite" => Importers.ImportTFLite(content, _compileSession),
"onnx" => Importers.ImportOnnx(content, _compileSession),
var inputFormat => throw new NotImplementedException($"Not Implement {inputFormat} Importer!"),
};
return _module;
}
private async Task RunPassAsync(Action<IPassManager> register, string name)
{
var newName = $"{_runPassCount++}_" + name;

View File

@ -0,0 +1,35 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IO;
using Nncase.IR;
namespace Nncase;
public static class CompilerExtensions
{
public static async Task<IRModule> ImportModuleAsync(this ICompiler compiler, string modelFormat, string fileName, bool isBenchmarkOnly = false)
{
using var fileStream = File.OpenRead(fileName);
switch (modelFormat.ToUpperInvariant())
{
case "TFLITE":
return await compiler.ImportTFLiteModuleAsync(fileStream);
case "ONNX":
return await compiler.ImportOnnxModuleAsync(fileStream);
case "NCNN":
{
using var binStream = isBenchmarkOnly ? (Stream)new ZeroStream() : File.OpenRead(Path.ChangeExtension(fileName, "bin"));
return await compiler.ImportNcnnModuleAsync(fileStream, binStream);
}
default:
throw new NotSupportedException($"Unsupported model format: {modelFormat}");
}
}
}

View File

@ -63,7 +63,9 @@ public unsafe struct CApiMT
public delegate* unmanaged<IntPtr, IntPtr, IntPtr> CompileSessionCreatePtr;
public delegate* unmanaged<IntPtr, IntPtr> CompileSessionGetCompilerPtr;
public delegate* unmanaged<void> CompilerInitializePtr;
public delegate* unmanaged<IntPtr, IntPtr, IntPtr> CompilerImportModulePtr;
public delegate* unmanaged<IntPtr, IntPtr, IntPtr> CompilerImportTFLiteModulePtr;
public delegate* unmanaged<IntPtr, IntPtr, IntPtr> CompilerImportOnnxModulePtr;
public delegate* unmanaged<IntPtr, IntPtr, IntPtr, IntPtr> CompilerImportNcnnModulePtr;
public delegate* unmanaged<IntPtr, void> CompilerCompilePtr;
public delegate* unmanaged<IntPtr, IntPtr, void> CompilerGencodePtr;
public delegate* unmanaged<Runtime.TypeCode, IntPtr> DataTypeFromTypeCodePtr;
@ -131,7 +133,9 @@ public static unsafe class CApi
mt->CompileSessionCreatePtr = &CompileSessionCreate;
mt->CompileSessionGetCompilerPtr = &CompileSessionGetCompiler;
mt->CompilerInitializePtr = &CompilerInitialize;
mt->CompilerImportModulePtr = &CompilerImportModule;
mt->CompilerImportTFLiteModulePtr = &CompilerImportTFLiteModule;
mt->CompilerImportOnnxModulePtr = &CompilerImportOnnxModule;
mt->CompilerImportNcnnModulePtr = &CompilerImportNcnnModule;
mt->CompilerCompilePtr = &CompilerCompile;
mt->CompilerGencodePtr = &CompilerGencode;
mt->DataTypeFromTypeCodePtr = &DataTypeFromTypeCode;
@ -395,11 +399,30 @@ public static unsafe class CApi
}
[UnmanagedCallersOnly]
private static IntPtr CompilerImportModule(IntPtr compilerHandle, IntPtr streamHandle)
private static IntPtr CompilerImportTFLiteModule(IntPtr compilerHandle, IntPtr streamHandle)
{
var compiler = Get<Compiler>(compilerHandle);
var stream = Get<CStream>(streamHandle);
var module = compiler.ImportModuleAsync(stream).Result;
var module = compiler.ImportTFLiteModuleAsync(stream).Result;
return GCHandle.ToIntPtr(GCHandle.Alloc(module));
}
[UnmanagedCallersOnly]
private static IntPtr CompilerImportOnnxModule(IntPtr compilerHandle, IntPtr streamHandle)
{
var compiler = Get<Compiler>(compilerHandle);
var stream = Get<CStream>(streamHandle);
var module = compiler.ImportOnnxModuleAsync(stream).Result;
return GCHandle.ToIntPtr(GCHandle.Alloc(module));
}
[UnmanagedCallersOnly]
private static IntPtr CompilerImportNcnnModule(IntPtr compilerHandle, IntPtr ncnnParamHandle, IntPtr ncnnBinHandle)
{
var compiler = Get<Compiler>(compilerHandle);
var ncnnParam = Get<CStream>(ncnnParamHandle);
var ncnnBin = Get<CStream>(ncnnBinHandle);
var module = compiler.ImportNcnnModuleAsync(ncnnParam, ncnnBin).Result;
return GCHandle.ToIntPtr(GCHandle.Alloc(module));
}

View File

@ -49,11 +49,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Google.OrTools.runtime.linux-arm64": {
@ -350,8 +350,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -114,4 +114,9 @@ public sealed record CompileOptions
/// Gets or sets quant options.
/// </summary>
public ShapeBucketOptions ShapeBucketOptions { get; set; } = ShapeBucketOptions.Default;
/// <summary>
/// Gets or sets a value indicating whether is benchmark only.
/// </summary>
public bool IsBenchmarkOnly { get; set; }
}

View File

@ -16,11 +16,26 @@ namespace Nncase;
public interface ICompiler
{
/// <summary>
/// Import DL model as ir module.
/// Import TFLite model as ir module.
/// </summary>
/// <param name="content">Model content.</param>
/// <returns>Imported ir module.</returns>
Task<IRModule> ImportModuleAsync(Stream content);
Task<IRModule> ImportTFLiteModuleAsync(Stream content);
/// <summary>
/// Import Onnx model as ir module.
/// </summary>
/// <param name="content">Model content.</param>
/// <returns>Imported ir module.</returns>
Task<IRModule> ImportOnnxModuleAsync(Stream content);
/// <summary>
/// Import Ncnn model as ir module.
/// </summary>
/// <param name="ncnnParam">Ncnn param stream.</param>
/// <param name="ncnnBin">Ncnn bin stream.</param>
/// <returns>Imported ir module.</returns>
Task<IRModule> ImportNcnnModuleAsync(Stream ncnnParam, Stream ncnnBin);
/// <summary>
/// import ir module into compiler.

View File

@ -150,5 +150,15 @@ namespace Nncase.IR
{
return Value.HasValue && predicate(Value.Value);
}
public bool IsAssignableFrom(Dimension dimension)
{
if (IsUnknown)
{
return true;
}
return dimension.Kind == DimensionKind.Fixed && Value == dimension.Value;
}
}
}

View File

@ -44,6 +44,8 @@ public static class NN
public static Call LRN(Expr input, Expr alpha, Expr beta, Expr bias, Expr size) => new Call(new LRN(), input, alpha, beta, bias, size);
public static Call Mish(Expr input) => input * Math.Tanh(Softplus(input));
public static Call HardSigmoid(Expr input, Expr alpha, Expr beta) => new Call(new HardSigmoid(), input, alpha, beta);
public static Call HardSwish(Expr input) => new Call(new HardSwish(), input);

View File

@ -316,6 +316,29 @@ namespace Nncase.IR
return other is Shape shape && Equals(shape);
}
public bool IsAssignableFrom(Shape shape)
{
if (IsUnranked)
{
return true;
}
if (shape.IsUnranked || Rank != shape.Rank)
{
return false;
}
for (int i = 0; i < _dimensions.Length; i++)
{
if (!_dimensions[i].IsAssignableFrom(shape[i]))
{
return false;
}
}
return true;
}
private static ShapeKind KindOf(ReadOnlySpan<Dimension> dimensions)
{
return dimensions.AsValueEnumerable().Any(x => x.IsUnknown) ? ShapeKind.HasUnknownDimension : ShapeKind.Fixed;

View File

@ -60,6 +60,8 @@ public unsafe sealed partial class Tensor<T> : Tensor, IEnumerable<T>, ICollecti
Buffer = buffer;
}
public static Tensor<T> Empty { get; } = new Tensor<T>(0);
/// <summary>
/// Gets memory storing backing values of this tensor.
/// </summary>

View File

@ -60,11 +60,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"System.Reactive": {
@ -109,8 +109,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -4,11 +4,11 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
@ -47,8 +47,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -41,11 +41,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Google.OrTools.runtime.linux-arm64": {
@ -140,8 +140,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -13,11 +13,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"libortki": {
@ -87,8 +87,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -4,11 +4,11 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"libortki": {
@ -78,8 +78,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -0,0 +1,51 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nncase.IO;
public sealed class ZeroStream : Stream
{
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => 0;
public override long Position { get; set; }
public override void Flush()
{
}
public override int Read(byte[] buffer, int offset, int count) => count;
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
Position = offset;
break;
case SeekOrigin.Current:
Position += offset;
break;
case SeekOrigin.End:
Position = 0;
break;
}
return Position;
}
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
}

View File

@ -4,17 +4,17 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
}
}
}

View File

@ -8,6 +8,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.Importer;
using Nncase.Importer.Ncnn;
using Nncase.Importer.TFLite;
using Nncase.IR;
@ -45,4 +46,18 @@ public static class Importers
var importer = new OnnxImporter(onnx, compileSession);
return importer.Import();
}
/// <summary>
/// Import ncnn model.
/// </summary>
/// <param name="ncnnParam">Ncnn param stream.</param>
/// <param name="ncnnBin">Ncnn bin stream.</param>
/// <param name="compileSession">compile session.</param>
/// <returns>Imported IR module.</returns>
public static IRModule ImportNcnn(Stream ncnnParam, Stream ncnnBin, CompileSession compileSession)
{
compileSession.CompileOptions.ModelLayout = "NCHW";
var importer = new NcnnImporter(ncnnParam, ncnnBin, compileSession);
return importer.Import();
}
}

View File

@ -0,0 +1,27 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IR;
using Nncase.IR.Buffers;
using Nncase.IR.F;
using Nncase.IR.NN;
namespace Nncase.Importer.Ncnn;
public partial class NcnnImporter
{
private Expr VisitConcat(NcnnLayer layer)
{
var axis = layer.ParamDict.Get(0, 0);
var inputs = GetInputExprs(layer).ToArray();
var output = Tensors.Concat(new IR.Tuple(inputs), axis);
return output;
}
}

View File

@ -0,0 +1,101 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Nncase.IR;
using Nncase.IR.Buffers;
using Nncase.IR.F;
using Nncase.IR.NN;
namespace Nncase.Importer.Ncnn;
public partial class NcnnImporter
{
private Expr VisitConvolution(NcnnLayer layer)
{
var numOutput = layer.ParamDict.Get(0, 0);
var kernelW = layer.ParamDict.Get(1, 0);
var kernelH = layer.ParamDict.Get(11, kernelW);
var dilationW = layer.ParamDict.Get(2, 1);
var dilationH = layer.ParamDict.Get(12, dilationW);
var strideW = layer.ParamDict.Get(3, 1);
var strideH = layer.ParamDict.Get(13, strideW);
var padLeft = layer.ParamDict.Get(4, 0);
var padRight = layer.ParamDict.Get(15, padLeft);
var padTop = layer.ParamDict.Get(14, padLeft);
var padBottom = layer.ParamDict.Get(16, padTop);
var padValue = layer.ParamDict.Get(18, 0.0f);
var biasTerm = layer.ParamDict.Get(5, 0);
var weightDataSize = layer.ParamDict.Get(6, 0);
var group = layer.ParamDict.Get(7, 1);
var activationType = layer.ParamDict.Get(9, 0);
var activationParams = layer.ParamDict.Get(10, Tensor<float>.Empty).Buffer.Span;
var numInput = weightDataSize / numOutput / kernelW / kernelH;
var kernelExtentW = (dilationW * (kernelW - 1)) + 1;
var kernelExtentH = (dilationH * (kernelH - 1)) + 1;
if (padValue != 0)
{
throw new NotSupportedException($"Unsupported pad value: {padValue}.");
}
var input = CHWToNCHW(GetInputExprs(layer, 0));
Expr[] paddingH;
Expr[] paddingW;
if (padLeft is -233 or -234)
{
var inShape = Tensors.ShapeOf(input);
var w = inShape[3];
var h = inShape[2];
var padW = kernelExtentW + ((w - 1) / strideW * strideW) - w;
var padH = kernelExtentH + ((h - 1) / strideH * strideH) - h;
if (padLeft == -233)
{
// SAME_UPPER
paddingH = new[] { padH / 2, padH - (padH / 2) };
paddingW = new[] { padW / 2, padW - (padW / 2) };
}
else
{
// SAME_LOWER
paddingH = new[] { padH - (padH / 2), padH / 2 };
paddingW = new[] { padW - (padW / 2), padW / 2 };
}
}
else
{
paddingH = new Expr[] { padTop, padBottom };
paddingW = new Expr[] { padLeft, padRight };
}
var stride = Tensor.From(new[] { strideH, strideW }, new[] { 2 });
var dilation = Tensor.From(new[] { dilationH, dilationW }, new[] { 2 });
var clampRange = ToFloatClampRange(activationType, activationParams);
var clamp = Tensor.From(new[] { clampRange.Min, clampRange.Max }, new[] { 2 });
var padding = Util.ConcatPadding(paddingH, paddingW);
var weights = _modelBin.LoadFloat32(new[] { numOutput, numInput, kernelH, kernelW }, true);
var bias = biasTerm != 0 ? _modelBin.LoadFloat32(new[] { numOutput }, false) : Tensor.FromScalar(0f, numOutput);
var conv2d = NN.Conv2D(input, weights, bias, stride, padding, dilation, PadMode.Constant, group, clamp);
conv2d = activationType switch
{
0 or 1 or 3 => conv2d,
2 => NN.LeakyRelu(conv2d, activationParams[0]),
4 => NN.Sigmoid(conv2d),
5 => NN.Mish(conv2d),
_ => throw new NotSupportedException($"Unsupported activation type: {activationType}."),
};
var output = NCHWToCHW(conv2d);
return output;
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Nncase.IR;
using Nncase.IR.Buffers;
using Nncase.IR.F;
using Nncase.IR.NN;
namespace Nncase.Importer.Ncnn;
public partial class NcnnImporter
{
private Expr VisitInnerProduct(NcnnLayer layer)
{
var numOutput = layer.ParamDict.Get(0, 0);
var biasTerm = layer.ParamDict.Get(1, 0) != 0;
var weightDataSize = layer.ParamDict.Get(2, 0);
var activationType = layer.ParamDict.Get(9, 0);
var activationParams = layer.ParamDict.Get(10, Tensor<float>.Empty).Buffer.Span;
var numInput = weightDataSize / numOutput;
var input = Tensors.Unsqueeze(GetInputExprs(layer, 0), new[] { 0 });
var weights = Tensors.Transpose(_modelBin.LoadFloat32(new[] { numOutput, numInput }, true), new[] { 1, 0 });
Expr output = IR.F.Math.MatMul(input, weights);
if (biasTerm)
{
output += _modelBin.LoadFloat32(new[] { numOutput }, false);
}
output = ApplyActivation(output, activationType, activationParams);
output = Tensors.Squeeze(output, new[] { 0 });
return output;
}
}

View File

@ -0,0 +1,156 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FlatBuffers;
using LanguageExt;
using NetFabric.Hyperlinq;
using Nncase.IR;
using Nncase.IR.F;
using Nncase.IR.Math;
using Nncase.IR.NN;
using Nncase.IR.Tensors;
using Math = System.Math;
using Tuple = Nncase.IR.Tuple;
namespace Nncase.Importer.Ncnn;
/// <summary>
/// Ncnn importer.
/// </summary>
public sealed partial class NcnnImporter : BaseImporter
{
private static readonly Dictionary<tflite.TensorType, DataType> _typeMap = new()
{
{ tflite.TensorType.BOOL, DataTypes.Boolean },
{ tflite.TensorType.FLOAT16, DataTypes.Float16 },
{ tflite.TensorType.FLOAT32, DataTypes.Float32 },
{ tflite.TensorType.FLOAT64, DataTypes.Float64 },
{ tflite.TensorType.INT16, DataTypes.Int16 },
{ tflite.TensorType.INT32, DataTypes.Int32 },
{ tflite.TensorType.INT64, DataTypes.Int64 },
{ tflite.TensorType.INT8, DataTypes.Int8 },
{ tflite.TensorType.STRING, DataTypes.Utf8Char },
{ tflite.TensorType.UINT32, DataTypes.UInt32 },
{ tflite.TensorType.UINT64, DataTypes.UInt64 },
{ tflite.TensorType.UINT8, DataTypes.UInt8 },
};
private readonly NcnnModel _model;
private readonly NcnnModelBin _modelBin;
private readonly Dictionary<string, Expr> _outputTensors = new Dictionary<string, Expr>();
/// <summary>
/// Initializes a new instance of the <see cref="NcnnImporter"/> class.
/// </summary>
/// <param name="ncnnParam">Ncnn param stream.</param>
/// <param name="ncnnBin">Ncnn bin stream.</param>
/// <param name="compileSession">Compile session.</param>
public NcnnImporter(Stream ncnnParam, Stream ncnnBin, CompileSession compileSession)
: base(compileSession)
{
_model = NcnnModel.ParseFromStream(ncnnParam);
_modelBin = new NcnnModelBin(ncnnBin);
}
/// <inheritdoc/>
protected override (IEnumerable<Var> Inputs, Dictionary<Var, Expr[]> VarMap) CreateInputs()
{
var inputs = new List<Var>();
var varMap = new Dictionary<Var, Expr[]>();
foreach (var layer in _model.Layers.Where(x => x.Type == "Input"))
{
var input = new Var(layer.Name, TensorType.Unranked(DataTypes.Float32));
inputs.Add(input);
_outputTensors.Add(layer.Name, input);
}
return (inputs, varMap);
}
protected override void ConvertOp()
{
foreach (var layer in _model.Layers.Where(x => x.Type != "Input"))
{
Visit(layer);
}
}
protected override Expr CreateOutputs()
{
var outputTensors = (from l in _model.Layers
from t in l.Tops
select t).Select((x, i) => (x.Name, i)).ToDictionary(x => x.Name, x => x.i);
var unusedTensors = (from t in outputTensors.Keys.Except(from l in _model.Layers
from t in l.Bottoms
select t.Name)
orderby outputTensors[t]
select t).ToArray();
var outputs = unusedTensors.Select(x => _outputTensors[x]).ToArray();
var body = outputs.Length > 1 ? new IR.Tuple(outputs) : outputs[0];
return body;
}
private static Expr CHWToNCHW(Expr expr) =>
Tensors.Unsqueeze(expr, new[] { 0 });
private static Expr NCHWToCHW(Expr expr) =>
Tensors.Squeeze(expr, new[] { 0 });
private static ValueRange<float> ToFloatClampRange(int activationType, ReadOnlySpan<float> activationParams) =>
activationType switch
{
1 => new(0, float.PositiveInfinity),
3 => new(activationParams[0], activationParams[1]),
_ => ValueRange<float>.Full,
};
private static Expr ApplyActivation(Expr input, int activationType, ReadOnlySpan<float> activationParams) =>
activationType switch
{
0 => input,
1 => NN.Relu(input),
2 => NN.LeakyRelu(input, activationParams[0]),
3 => IR.F.Math.Clamp(input, activationParams[0], activationParams[1]),
4 => NN.Sigmoid(input),
5 => NN.Mish(input),
_ => throw new NotSupportedException($"Unsupported activation type: {activationType}."),
};
private void Visit(NcnnLayer layer)
{
var output = layer.Type switch
{
"Concat" => VisitConcat(layer),
"Convolution" => VisitConvolution(layer),
"ConvolutionDepthWise" => VisitConvolution(layer),
"InnerProduct" => VisitInnerProduct(layer),
"Pooling" => VisitPooling(layer),
"ShuffleChannel" => VisitShuffleChannel(layer),
"Softmax" => VisitSoftmax(layer),
"Split" => VisitSplit(layer),
_ => UnSupportedOp(layer.Type),
};
var outputNames = layer.Tops.Select(x => x.Name).ToArray();
output.Metadata.OutputNames = outputNames;
AddToOutputs(_outputTensors, outputNames, output);
}
private Expr GetInputExprs(NcnnLayer layer, int index) =>
_outputTensors[layer.Bottoms[index].Name];
private (Expr Expr0, Expr Expr1) GetInputExprs(NcnnLayer layer, int index0, int index1) =>
(GetInputExprs(layer, index0), GetInputExprs(layer, index1));
private IEnumerable<Expr> GetInputExprs(NcnnLayer layer) =>
layer.Bottoms.Select(x => _outputTensors[x.Name]);
}

View File

@ -0,0 +1,108 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IR;
namespace Nncase.Importer.Ncnn;
internal class NcnnTensor
{
public string Name { get; set; } = string.Empty;
public Shape ShapeHint { get; set; } = Shape.Unranked;
public override string ToString() => $"{Name}: {ShapeHint}";
}
internal class NcnnLayer
{
public NcnnLayer(string type, string name, int bottomCount, int topCount)
{
Type = type;
Name = name;
Bottoms = new NcnnTensor[bottomCount];
Tops = new NcnnTensor[topCount];
}
public string Type { get; }
public string Name { get; }
public NcnnTensor[] Bottoms { get; }
public NcnnTensor[] Tops { get; }
public ParamDict ParamDict { get; } = new();
public override string ToString() => $"[{Type}] {Name}";
}
internal class NcnnModel
{
public static readonly int ExpectedMagic = 7767517;
public NcnnModel(int magic, IReadOnlyList<NcnnLayer> layers)
{
Magic = magic;
Layers = layers;
}
public int Magic { get; }
public IReadOnlyList<NcnnLayer> Layers { get; }
public static NcnnModel ParseFromStream(Stream stream)
{
using var reader = new StreamReader(stream, leaveOpen: true);
if (reader.ReadLine() is not string magicStr)
{
throw new InvalidDataException("parse magic failed");
}
if (reader.ReadLine()?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) is not [var layerCountStr, var blobCountStr])
{
throw new InvalidDataException("parse layer_count or blob_count failed");
}
var magic = int.Parse(magicStr);
if (magic != ExpectedMagic)
{
throw new InvalidDataException("param is too old, please regenerate");
}
var layerCount = int.Parse(layerCountStr);
var blobCount = int.Parse(blobCountStr);
if (layerCount <= 0 || blobCount <= 0)
{
throw new InvalidDataException("invalid layer_count or blob_count");
}
var layers = new NcnnLayer[layerCount];
foreach (ref var layer in layers.AsSpan())
{
var fields = reader.ReadLine()!.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
layer = new NcnnLayer(fields[0], fields[1], int.Parse(fields[2]), int.Parse(fields[3]));
int cntFieldIndex = 4;
foreach (ref var bottom in layer.Bottoms.AsSpan())
{
bottom = new NcnnTensor { Name = fields[cntFieldIndex++] };
}
foreach (ref var top in layer.Tops.AsSpan())
{
top = new NcnnTensor { Name = fields[cntFieldIndex++] };
}
layer.ParamDict.LoadFrom(fields.AsSpan(cntFieldIndex));
}
return new NcnnModel(magic, layers);
}
}

View File

@ -0,0 +1,72 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Toolkit.HighPerformance;
namespace Nncase.Importer.Ncnn;
internal class NcnnModelBin
{
private readonly Stream _stream;
public NcnnModelBin(Stream stream)
{
_stream = stream;
}
public Tensor<float> LoadFloat32(ReadOnlySpan<int> shape, bool detectType)
{
if (!detectType)
{
var tensor = new Tensor<float>(shape);
_stream.ReadExactly(tensor.BytesBuffer);
return tensor;
}
else
{
return LoadAuto(shape).Cast<float>();
}
}
public Tensor LoadAuto(ReadOnlySpan<int> shape)
{
uint tag;
Unsafe.SkipInit(out tag);
_stream.ReadExactly(MemoryMarshal.CreateSpan(ref tag, 1).AsBytes());
if (tag == 0x01306B47)
{
// half-precision data
var tensor = new Tensor<Half>(shape);
_stream.ReadExactly(tensor.BytesBuffer);
AlignStream(_stream, tensor.BytesBuffer.Length, 4);
return tensor.Cast<float>(CastMode.KDefault);
}
else if (tag == 0)
{
// raw data
var tensor = new Tensor<float>(shape);
_stream.ReadExactly(tensor.BytesBuffer);
return tensor;
}
else
{
throw new NotSupportedException($"Unsupported weight tag: {tag}.");
}
}
private static void AlignStream(Stream stream, int size, int alignment)
{
var rem = size % alignment;
var offset = rem == 0 ? 0 : alignment - rem;
stream.Seek(offset, SeekOrigin.Current);
}
}

View File

@ -0,0 +1,119 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Google.Protobuf.WellKnownTypes;
using Nncase.IR;
namespace Nncase.Importer.Ncnn;
internal enum ParamKind
{
Null,
IntOrFloat,
Int,
Float,
ArrayOfIntOrFloat,
ArrayOfInt,
ArrayOfFloat,
}
internal struct ParamValue
{
public ParamKind Kind;
public int IntValue;
public float FloatValue;
public Tensor? TensorValue;
}
internal class ParamDict
{
public static readonly int NcnnMaxParamCount = 32;
private readonly Dictionary<int, ParamValue> _values = new();
public void LoadFrom(ReadOnlySpan<string> fields)
{
foreach (var field in fields)
{
if (field.Split('=', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) is not [var idStr, var valueStr])
{
break;
}
var id = int.Parse(idStr);
if (id >= NcnnMaxParamCount)
{
throw new InvalidDataException($"id < NCNN_MAX_PARAM_COUNT failed (id={id}, NCNN_MAX_PARAM_COUNT={NcnnMaxParamCount})");
}
var paramValue = default(ParamValue);
var isArray = id <= -23300;
var isFloat = valueStr.AsSpan().IndexOfAny('.', 'e', 'E') != -1;
if (isArray)
{
id = -id - 23300;
var elements = valueStr.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (elements == null || elements.Length == 0)
{
throw new InvalidDataException("ParamDict read array length failed");
}
var length = int.Parse(elements[0]);
if (isFloat)
{
var value = new Tensor<float>(length);
for (var i = 0; i < length; i++)
{
value[i] = float.Parse(elements[i + 1]);
}
paramValue.Kind = ParamKind.ArrayOfFloat;
paramValue.TensorValue = value;
}
else
{
var value = new Tensor<int>(length);
for (var i = 1; i < length; i++)
{
value[i] = int.Parse(elements[i + 1]);
}
paramValue.Kind = ParamKind.ArrayOfInt;
paramValue.TensorValue = value;
}
}
else
{
if (isFloat)
{
paramValue.Kind = ParamKind.Float;
paramValue.FloatValue = float.Parse(valueStr);
}
else
{
paramValue.Kind = ParamKind.Int;
paramValue.IntValue = int.Parse(valueStr);
}
}
_values.Add(id, paramValue);
}
}
public int Get(int id, int defaultValue) => _values.TryGetValue(id, out var value) ? value.IntValue : defaultValue;
public float Get(int id, float defaultValue) => _values.TryGetValue(id, out var value) ? value.FloatValue : defaultValue;
public Tensor<T> Get<T>(int id, Tensor<T> defaultValue)
where T : unmanaged, IEquatable<T>
=> _values.TryGetValue(id, out var value) ? value.TensorValue!.Cast<T>() : defaultValue;
}

View File

@ -0,0 +1,127 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IR;
using Nncase.IR.Buffers;
using Nncase.IR.F;
using Nncase.IR.NN;
namespace Nncase.Importer.Ncnn;
public partial class NcnnImporter
{
private Expr VisitPooling(NcnnLayer layer)
{
var poolingType = layer.ParamDict.Get(0, 0);
var kernelW = layer.ParamDict.Get(1, 0);
var kernelH = layer.ParamDict.Get(11, kernelW);
var strideW = layer.ParamDict.Get(2, 1);
var strideH = layer.ParamDict.Get(12, strideW);
var padLeft = layer.ParamDict.Get(3, 0);
var padRight = layer.ParamDict.Get(14, padLeft);
var padTop = layer.ParamDict.Get(13, padLeft);
var padBottom = layer.ParamDict.Get(15, padTop);
var globalPooling = layer.ParamDict.Get(4, 0) != 0;
var padMode = layer.ParamDict.Get(5, 0);
var avgpoolCountIncludePad = layer.ParamDict.Get(6, 0) != 0;
var adaptivePooling = layer.ParamDict.Get(7, 0) != 0;
var outW = layer.ParamDict.Get(8, 0);
var outH = layer.ParamDict.Get(18, outW);
Expr pooling;
var input = CHWToNCHW(GetInputExprs(layer, 0));
(var reduceOp, var initValue) = poolingType switch
{
0 => (ReduceOp.Max, float.NegativeInfinity),
1 => (ReduceOp.Mean, 0f),
_ => throw new NotSupportedException($"Unsupported pooling type: {poolingType}."),
};
var filter = Tensor.From(new[] { kernelH, kernelW }, new[] { 2 });
var stride = Tensor.From(new[] { strideH, strideW }, new[] { 2 });
var dilation = Tensor.FromScalar(0, new[] { 2, 2 });
if (globalPooling)
{
pooling = Tensors.Reduce(reduceOp, input, new[] { 2, 3 }, initValue, false);
}
else if (adaptivePooling)
{
var padding = Tensor.FromScalar(0, new[] { 2, 2 });
var inShape = Tensors.ShapeOf(input);
var w = inShape[3];
var h = inShape[2];
var kernelExtentH = h - outH + 1;
var kernelExtentW = w - outW + 1;
var adaptiveFilter = Tensors.Stack(new IR.Tuple(kernelExtentH, kernelExtentW), 0);
var adaptiveStride = Tensor.FromScalar(1, 2);
pooling = NN.ReduceWindow2D(reduceOp, input, initValue, adaptiveFilter, adaptiveStride, padding, dilation, false, avgpoolCountIncludePad);
}
else
{
Expr[] paddingH;
Expr[] paddingW;
if (padMode == 1)
{
// valid padding
paddingH = new Expr[] { padTop, padBottom };
paddingW = new Expr[] { padLeft, padRight };
}
else
{
var inShape = Tensors.ShapeOf(input);
var w = inShape[3];
var h = inShape[2];
if (padMode == 0)
{
// full padding
var tailW = (w + padLeft + padRight - kernelW) % strideW;
var tailH = (h + padTop + padBottom - kernelH) % strideH;
var tailPadW = IR.F.Math.Select(IR.F.Math.Equal(tailW, 0), 0, tailW);
var tailPadH = IR.F.Math.Select(IR.F.Math.Equal(tailH, 0), 0, tailH);
paddingH = new Expr[] { padTop, padBottom + tailPadH };
paddingW = new Expr[] { padLeft, padRight + tailPadW };
}
else if (padMode is 2 or 3)
{
// valid padding
var padH = kernelH + ((h - 1) / strideH * strideH) - h;
var padW = kernelW + ((w - 1) / strideW * strideW) - w;
if (padMode == 2)
{
// tensorflow padding=SAME or onnx padding=SAME_UPPER
paddingH = new Expr[] { padH / 2, padH - (padH / 2) };
paddingW = new Expr[] { padW / 2, padW - (padW / 2) };
}
else
{
// onnx padding=SAME_LOWER
paddingH = new Expr[] { padH - (padH / 2), padH / 2 };
paddingW = new Expr[] { padW - (padW / 2), padW / 2 };
}
}
else
{
throw new NotSupportedException($"Unsupported pad mode: {padMode}.");
}
}
var padding = Util.ConcatPadding(paddingH, paddingW);
pooling = NN.ReduceWindow2D(reduceOp, input, initValue, filter, stride, padding, dilation, false, avgpoolCountIncludePad);
}
var output = NCHWToCHW(pooling);
return output;
}
}

View File

@ -0,0 +1,37 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IR;
using Nncase.IR.Buffers;
using Nncase.IR.F;
using Nncase.IR.NN;
namespace Nncase.Importer.Ncnn;
public partial class NcnnImporter
{
private Expr VisitShuffleChannel(NcnnLayer layer)
{
var group = layer.ParamDict.Get(0, 1);
var reverse = layer.ParamDict.Get(1, 0) != 0;
var input = GetInputExprs(layer, 0);
var inShape = Tensors.ShapeOf(input);
var channels = inShape[0];
var h = inShape[1];
var w = inShape[2];
var realGroup = reverse ? channels / group : (Expr)group;
var channelsPerGroup = channels / realGroup;
var rshape1 = Tensors.Reshape(input, Tensors.Stack(new IR.Tuple(realGroup, channelsPerGroup, h, w), 0));
var tp = Tensors.Transpose(rshape1, new[] { 1, 0, 2, 3 });
var output = Tensors.Reshape(tp, Tensors.Stack(new IR.Tuple(channels, h, w), 0));
return output;
}
}

View File

@ -0,0 +1,27 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IR;
using Nncase.IR.Buffers;
using Nncase.IR.F;
using Nncase.IR.NN;
namespace Nncase.Importer.Ncnn;
public partial class NcnnImporter
{
private Expr VisitSoftmax(NcnnLayer layer)
{
var axis = layer.ParamDict.Get(0, 0);
var input = GetInputExprs(layer, 0);
var output = NN.Softmax(input, axis);
return output;
}
}

View File

@ -0,0 +1,25 @@
// Copyright (c) Canaan Inc. All rights reserved.
// Licensed under the Apache license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IR;
using Nncase.IR.Buffers;
using Nncase.IR.F;
using Nncase.IR.NN;
namespace Nncase.Importer.Ncnn;
public partial class NcnnImporter
{
private Expr VisitSplit(NcnnLayer layer)
{
var input = GetInputExprs(layer, 0);
var output = new IR.Tuple(Enumerable.Repeat(input, layer.Tops.Length).ToArray());
return output;
}
}

View File

@ -22,11 +22,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
@ -85,8 +85,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -16,6 +16,7 @@ using static Nncase.PatternMatch.Utility;
using static Nncase.Utilities.ReplaceUtility;
namespace Nncase.Passes.Rules.ShapeBucket;
public abstract class MergeFusionBase : RewriteRule<Pattern>
{
protected int Counter { get; set; }

View File

@ -4,11 +4,11 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Google.OrTools.runtime.linux-arm64": {
@ -103,8 +103,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -113,19 +113,9 @@ public class CalibrationEvaluator : IDisposable
};
}
private bool ShapeChecker(Shape current, Shape target)
{
if (current.Count != target.Count)
{
return false;
}
return current.Zip(target).All(p => p.Second.IsUnknown ? true : p.Second.FixedValue == p.First.FixedValue);
}
private bool TypeChecker(IRType cur_type, IRType target_type) => (cur_type, target_type) switch
{
(TensorType a, TensorType b) => a.DType == b.DType && ShapeChecker(a.Shape, b.Shape),
(TensorType a, TensorType b) => a.DType == b.DType && b.Shape.IsAssignableFrom(a.Shape),
(TupleType a, TupleType b) => a.Zip(b).All(p => TypeChecker(p.First, p.Second)),
(_, _) => true,
};

View File

@ -19,11 +19,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"System.Linq.Async": {
@ -132,8 +132,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -4,11 +4,11 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
@ -47,8 +47,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -4,11 +4,11 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
@ -47,8 +47,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -4,11 +4,11 @@
"net7.0": {
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
@ -47,8 +47,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -42,9 +42,9 @@ namespace Nncase.Tests
CompileOptions.QuantizeOptions.UseSquant = false;
CompileOptions.DumpFlags = DumpFlags.Rewrite;
using var file = File.OpenRead(ModelPath());
CompileOptions.InputFormat = Path.GetExtension(file.Name).Trim('.');
var m = await CompileSession.Compiler.ImportModuleAsync(file);
var modelPath = ModelPath();
CompileOptions.InputFormat = Path.GetExtension(modelPath).Trim('.');
var m = await CompileSession.Compiler.ImportModuleAsync(CompileOptions.InputFormat, modelPath);
var types = m.Entry!.ParameterTypes.Select(type => (TensorType)type!).ToArray();
var shapes = types.Select(x => x.Shape).ToArray();
var isDynamic = shapes.Any(shape => !shape.IsFixed);

View File

@ -4,13 +4,15 @@
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>Nncase.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Fody">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MethodBoundaryAspect.Fody" />
<PackageReference Include="NETStandard.Library" />
<PackageReference Include="Xunit.Combinatorial" />
<PackageReference Include="Xunit.DependencyInjection" />
<PackageReference Include="System.Linq.Async" />
@ -20,9 +22,10 @@
</PackageReference>
<PackageReference Include="xunit.v3.assert" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\Nncase.Modules.StackVM\Nncase.Modules.StackVM.csproj" />
<ProjectReference Include="..\Nncase.Compiler\Nncase.Compiler.csproj" />
<ProjectReference Include="..\Nncase.Core\Nncase.Core.csproj" />
<ProjectReference Include="..\Nncase.CodeGen\Nncase.CodeGen.csproj" />
<ProjectReference Include="..\Nncase.Simulator\Nncase.Simulator.csproj" />

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nncase.IO;
using Nncase.IR;
using Nncase.Passes.Transforms;
using Nncase.Tests.TestFixture;
@ -37,6 +38,16 @@ public class UnitTestImporter : TestClassBase
Assert.True(module.Entry!.InferenceType());
}
[Fact]
public async Task TestImportNcnn()
{
using var file = File.OpenRead(Path.Combine(SolutionDirectory, "examples/user_guide/test.param"));
var module = Importers.ImportNcnn(file, new ZeroStream(), CompileSession);
await InferShapeAsync(module);
Assert.NotNull(module.Entry);
Assert.True(module.Entry!.InferenceType());
}
private Task InferShapeAsync(IRModule module)
{
var pmgr = CompileSession.CreatePassManager("InferShapePasses");

View File

@ -80,7 +80,7 @@ public sealed class UnitTestMutators : TestClassBase
var name = getBuffer(count++, LoadT.GlbPp).Name[^4..];
// System.Console.WriteLine($"{w} {name}");
if (((w / 9) % 2) == 0)
if ((w / 9 % 2) == 0)
{
Assert.Equal("ping", name);
}

View File

@ -80,11 +80,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"System.Linq.Async": {
@ -470,16 +470,6 @@
"Newtonsoft.Json": "9.0.1"
}
},
"Microsoft.Win32.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"NetFabric.Hyperlinq.Abstractions": {
"type": "Transitive",
"resolved": "1.3.0",
@ -487,53 +477,10 @@
},
"NETStandard.Library": {
"type": "Transitive",
"resolved": "1.6.1",
"contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==",
"resolved": "2.0.3",
"contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.Win32.Primitives": "4.3.0",
"System.AppContext": "4.3.0",
"System.Collections": "4.3.0",
"System.Collections.Concurrent": "4.3.0",
"System.Console": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.Tools": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Calendars": "4.3.0",
"System.IO": "4.3.0",
"System.IO.Compression": "4.3.0",
"System.IO.Compression.ZipFile": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Linq": "4.3.0",
"System.Linq.Expressions": "4.3.0",
"System.Net.Http": "4.3.0",
"System.Net.Primitives": "4.3.0",
"System.Net.Sockets": "4.3.0",
"System.ObjectModel": "4.3.0",
"System.Reflection": "4.3.0",
"System.Reflection.Extensions": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Security.Cryptography.X509Certificates": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Text.Encoding.Extensions": "4.3.0",
"System.Text.RegularExpressions": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0",
"System.Threading.Timer": "4.3.0",
"System.Xml.ReaderWriter": "4.3.0",
"System.Xml.XDocument": "4.3.0"
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
"NuGet.Frameworks": {
@ -541,125 +488,10 @@
"resolved": "5.0.0",
"contentHash": "c5JVjuVAm4f7E9Vj+v09Z9s2ZsqFDjBpcsyS3M9xRo0bEdm/LVZSzLxxNvfvAwRiiE8nwe1h2G4OwiwlzFKXlA=="
},
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q=="
},
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA=="
},
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw=="
},
"runtime.native.System": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"runtime.native.System.IO.Compression": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"runtime.native.System.Net.Http": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"runtime.native.System.Security.Cryptography.Apple": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==",
"dependencies": {
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0"
}
},
"runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
"dependencies": {
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A=="
},
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ=="
},
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ=="
},
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g=="
},
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg=="
},
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ=="
},
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A=="
},
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.AppContext": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==",
"dependencies": {
"System.Runtime": "4.3.0"
}
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",
@ -676,40 +508,11 @@
"System.Runtime": "4.3.0"
}
},
"System.Collections.Concurrent": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Globalization": "4.3.0",
"System.Reflection": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "7.0.0",
"contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ=="
},
"System.Console": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0"
}
},
"System.Diagnostics.Contracts": {
"type": "Transitive",
"resolved": "4.3.0",
@ -741,26 +544,6 @@
"resolved": "6.0.0",
"contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw=="
},
"System.Diagnostics.Tools": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Diagnostics.Tracing": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization": {
"type": "Transitive",
"resolved": "4.3.0",
@ -771,30 +554,6 @@
"System.Runtime": "4.3.0"
}
},
"System.Globalization.Calendars": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Globalization": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Globalization.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.InteropServices": "4.3.0"
}
},
"System.IO": {
"type": "Transitive",
"resolved": "4.3.0",
@ -807,67 +566,6 @@
"System.Threading.Tasks": "4.3.0"
}
},
"System.IO.Compression": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Buffers": "4.3.0",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.IO.Compression": "4.3.0"
}
},
"System.IO.Compression.ZipFile": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==",
"dependencies": {
"System.Buffers": "4.3.0",
"System.IO": "4.3.0",
"System.IO.Compression": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Text.Encoding": "4.3.0"
}
},
"System.IO.FileSystem": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.IO.FileSystem.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==",
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.Linq": {
"type": "Transitive",
"resolved": "4.3.0",
@ -924,63 +622,6 @@
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
},
"System.Net.Http": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.DiagnosticSource": "4.3.0",
"System.Diagnostics.Tracing": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Extensions": "4.3.0",
"System.IO": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.Net.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.OpenSsl": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Security.Cryptography.X509Certificates": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Net.Http": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Net.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0"
}
},
"System.Net.Sockets": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Net.Primitives": "4.3.0",
"System.Runtime": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.ObjectModel": {
"type": "Transitive",
"resolved": "4.3.0",
@ -1109,198 +750,6 @@
"System.Runtime": "4.3.0"
}
},
"System.Runtime.Handles": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.InteropServices": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Reflection": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Handles": "4.3.0"
}
},
"System.Runtime.InteropServices.RuntimeInformation": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Extensions": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Threading": "4.3.0",
"runtime.native.System": "4.3.0"
}
},
"System.Runtime.Numerics": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==",
"dependencies": {
"System.Globalization": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Security.Cryptography.Algorithms": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.Apple": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.Cng": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0"
}
},
"System.Security.Cryptography.Csp": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0"
}
},
"System.Security.Cryptography.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.Collections.Concurrent": "4.3.0",
"System.Linq": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.OpenSsl": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==",
"dependencies": {
"System.Collections": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Cryptography.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==",
"dependencies": {
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.IO": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Threading": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Security.Cryptography.X509Certificates": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.Globalization.Calendars": "4.3.0",
"System.IO": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.Handles": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Runtime.Numerics": "4.3.0",
"System.Security.Cryptography.Algorithms": "4.3.0",
"System.Security.Cryptography.Cng": "4.3.0",
"System.Security.Cryptography.Csp": "4.3.0",
"System.Security.Cryptography.Encoding": "4.3.0",
"System.Security.Cryptography.OpenSsl": "4.3.0",
"System.Security.Cryptography.Primitives": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"runtime.native.System": "4.3.0",
"runtime.native.System.Net.Http": "4.3.0",
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
@ -1311,17 +760,6 @@
"System.Runtime": "4.3.0"
}
},
"System.Text.Encoding.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0"
}
},
"System.Text.Encodings.Web": {
"type": "Transitive",
"resolved": "6.0.0",
@ -1339,14 +777,6 @@
"System.Text.Encodings.Web": "6.0.0"
}
},
"System.Text.RegularExpressions": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==",
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.Threading": {
"type": "Transitive",
"resolved": "4.3.0",
@ -1371,62 +801,11 @@
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
},
"System.Threading.Timer": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"System.Xml.ReaderWriter": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Globalization": "4.3.0",
"System.IO": "4.3.0",
"System.IO.FileSystem": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Runtime.InteropServices": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Text.Encoding.Extensions": "4.3.0",
"System.Text.RegularExpressions": "4.3.0",
"System.Threading.Tasks": "4.3.0",
"System.Threading.Tasks.Extensions": "4.3.0"
}
},
"System.Xml.XDocument": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==",
"dependencies": {
"System.Collections": "4.3.0",
"System.Diagnostics.Debug": "4.3.0",
"System.Diagnostics.Tools": "4.3.0",
"System.Globalization": "4.3.0",
"System.IO": "4.3.0",
"System.Reflection": "4.3.0",
"System.Resources.ResourceManager": "4.3.0",
"System.Runtime": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading": "4.3.0",
"System.Xml.ReaderWriter": "4.3.0"
}
},
"Tomlyn": {
"type": "Transitive",
"resolved": "0.14.3",
@ -1574,7 +953,9 @@
"type": "Project",
"dependencies": {
"MethodBoundaryAspect.Fody": "[2.0.148, )",
"NETStandard.Library": "[2.0.3, )",
"Nncase.CodeGen": "[1.0.0, )",
"Nncase.Compiler": "[1.0.0, )",
"Nncase.Core": "[1.0.0, )",
"Nncase.Modules.StackVM": "[1.0.0, )",
"Nncase.Passes": "[1.0.0, )",

View File

View File

View File

@ -0,0 +1,87 @@
# Copyright 2019-2021 Canaan Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# pylint: disable=invalid-name, unused-argument, import-outside-toplevel
import pytest
import numpy as np
from ncnn_test_runner import Net, NcnnTestRunner
def _make_module(i_channels, i_size, k_size, o_channels, strides, padding, dilations):
w = np.random.rand(*k_size, i_channels, o_channels).astype(np.float32) - 0.5
net = Net()
input = net.Input("input", i_size[1], i_size[0], i_channels)
net.Convolution("conv1", input, o_channels, k_size[1], k_size[0], dilations[1], dilations[0],
strides[1], strides[0], padding[0], padding[1], padding[2], padding[3], 0.0, w)
return net
i_channels = [
3,
16
]
i_sizes = [
[12, 24],
[38, 65]
]
k_sizes = [
[1, 1],
[3, 3],
]
o_channels = [
1,
8
]
strides = [
(1, 1),
(5, 5)
]
paddings = [
(1, 1, 1, 1)
]
padding_modes = [
'zeros'
]
dilations = [
[1, 1],
[2, 2]
]
@pytest.mark.parametrize('i_channels', i_channels)
@pytest.mark.parametrize('i_size', i_sizes)
@pytest.mark.parametrize('k_size', k_sizes)
@pytest.mark.parametrize('o_channels', o_channels)
@pytest.mark.parametrize('strides', strides)
@pytest.mark.parametrize('padding', paddings)
@pytest.mark.parametrize('dilations', dilations)
def test_conv2d(i_channels, i_size, k_size, o_channels, strides, padding, dilations, request):
module = _make_module(i_channels, i_size, k_size, o_channels,
strides, padding, dilations)
runner = NcnnTestRunner(request.node.name)
model_param, model_bin = runner.from_ncnn(module)
runner.run(model_param, model_bin)
if __name__ == "__main__":
pytest.main(['-vv', 'test_conv2d.py'])

209
tests/ncnn_test_runner.py Normal file
View File

@ -0,0 +1,209 @@
from posixpath import join
from typing import Sequence
import ncnn
import shutil
import os
import numpy as np
from numpy.core.defchararray import array
from numpy.lib.function_base import select
from test_runner import *
import io
class Layer:
def __init__(self, type: str, name: str, inputs: Sequence[str] = [], outputs: Sequence[str] = [], params: dict = {}) -> None:
self.type = type
self.name = name
self.inputs = inputs
self.outputs = outputs
self.params = params
def __str__(self) -> str:
s = f"{self.type} {self.name} {len(self.inputs)} {len(self.outputs)}"
s += ''.join([' ' + v for v in self.inputs])
s += ''.join([' ' + v for v in self.outputs])
s += ''.join([f" {k}={v}" for k, v in self.params.items()])
return s
def __repr__(self) -> str:
return str(self)
class Net:
def __init__(self) -> None:
self.layers = []
self.bin = io.BytesIO()
self.blobs = 0
def Input(self, name: str, w: int, h: int, c: int) -> str:
self._add_layer("Input", name, outputs=[name], params={'0': w, '1': h, '2': c})
return name
def Convolution(self, name: str, input: str, outch: int, kernel_w: int, kernel_h: int,
dilation_w: int, dilation_h: int, stride_w: int, stride_h: int,
pad_left: int, pad_right: int, pad_top: int, pad_bottom: int,
pad_value: float, weights: np.ndarray, bias: np.ndarray = None) -> str:
self._add_layer("Convolution", name, inputs=[input], outputs=[name], params={
'0': outch,
'1': kernel_w,
'11': kernel_h,
'2': dilation_w,
'12': dilation_h,
'3': stride_w,
'13': stride_h,
'4': pad_left,
'15': pad_right,
'14': pad_top,
'16': pad_bottom,
'18': pad_value,
'5': 0 if bias is None else 1,
'6': weights.size
})
self._add_bin(0, weights)
if bias is not None:
self._add_bin(1, bias)
return name
def Pooling(self, name: str, input: str, pooling_type: int, kernel_w: int, kernel_h: int,
stride_w: int, stride_h: int,
pad_left: int, pad_right: int, pad_top: int, pad_bottom: int,
global_pooling: bool, weights: np.ndarray, bias: np.ndarray = None) -> str:
self._add_layer("Pooling", name, inputs=[input], outputs=[name], params={
'0': pooling_type,
'1': kernel_w,
'11': kernel_h,
'2': stride_w,
'12': stride_h,
'3': pad_left,
'13': pad_right,
'4': pad_top,
'15': pad_bottom,
'4': 1 if global_pooling else 0,
'5': 0 if bias is None else 1,
'6': weights.size
})
self._add_bin(0, weights)
if bias is not None:
self._add_bin(1, bias)
return name
def _add_layer(self, type: str, name: str, inputs: Sequence[str] = [], outputs: Sequence[str] = [], params: dict = []):
self.layers.append(Layer(type, name, inputs, outputs, params))
self.blobs += len(outputs)
def _add_bin(self, tag: int, arr: np.ndarray):
self.bin.write(tag.to_bytes(4, byteorder='little'))
self.bin.write(arr.tobytes())
class NcnnTestRunner(TestRunner):
def __init__(self, case_name, overwrite_configs: str = None):
super().__init__(case_name, overwrite_configs)
self.model_type = "ncnn"
def from_ncnn(self, net: Net):
param_file = os.path.join(self.case_dir, 'test.param')
with open(param_file, 'w') as fp:
print("7767517", file=fp)
print(f"{len(net.layers)} {net.blobs}", file=fp)
for l in net.layers:
print(str(l), file=fp)
bin_file = os.path.join(self.case_dir, 'test.bin')
with open(bin_file, 'wb') as fb:
fb.write(net.bin.getbuffer())
return param_file, bin_file
def run(self, param_file, bin_file):
if self.case_dir != os.path.dirname(param_file):
new_file = os.path.join(self.case_dir, 'test.param')
shutil.copy(param_file, new_file)
param_file = new_file
if self.case_dir != os.path.dirname(bin_file):
new_file = os.path.join(self.case_dir, 'test.bin')
shutil.copy(bin_file, new_file)
bin_file = new_file
if not self.inputs:
self.parse_model(param_file)
super().run([param_file, bin_file])
def parse_model(self, param_file: str):
all_inputs = []
all_outputs = []
with open(param_file, 'r') as fp:
for line in fp:
tokens = line.split(' ', 4)
if len(tokens) < 4:
continue
op_type = tokens[0]
name = tokens[1]
in_num = int(tokens[2])
out_num = int(tokens[3])
tokens = tokens[-1].split(' ', in_num)
inputs = tokens[:in_num]
tokens = tokens[-1].split(' ', out_num)
outputs = tokens[:out_num]
all_inputs += inputs
all_outputs += outputs
if op_type != 'Input':
continue
param_kvs = []
for kv in tokens[-1].split(' '):
kv_tokens = kv.split('=')
param_kvs.append((int(kv_tokens[0]), int(kv_tokens[1])))
params = dict(param_kvs)
input_dict = {}
input_dict['name'] = outputs[0]
input_dict['dtype'] = np.float32
shape = [params[2], params[1], params[0]]
input_dict['shape'] = shape
input_dict['model_shape'] = shape
self.inputs.append(input_dict)
self.calibs.append(copy.deepcopy(input_dict))
used_inputs = set(inputs)
seen_outputs = set()
for n in all_outputs:
if not n in used_inputs and not n in seen_outputs:
seen_outputs.add(n)
input_dict = {}
input_dict['name'] = n
self.outputs.append(input_dict)
def cpu_infer(self, model_file: List[str]):
outputs = []
with ncnn.Net() as net:
ret = net.load_param(model_file[0])
assert ret == 0
ret = net.load_model(model_file[1])
assert ret == 0
with net.create_extractor() as ex:
for input in self.inputs:
new_value = self.transform_input(
self.data_pre_process(input['data']), "float32", "CPU")[0]
in_mat = ncnn.Mat(new_value)
ex.input(input['name'], in_mat)
if self.cfg['compile_opt']['preprocess'] and not test_utils.in_ci():
dump_bin_file(os.path.join(self.case_dir, f'frame_input_{i}.bin'), new_value)
dump_txt_file(os.path.join(self.case_dir, f'frame_input_{i}.txt'), new_value)
i = 0
for output in self.outputs:
out_mat = ncnn.Mat()
ex.extract(output['name'], out_mat)
out_arr = np.array(out_mat)
out_mat.release()
outputs.append(out_arr)
if not test_utils.in_ci():
dump_bin_file(os.path.join(self.case_dir, f'cpu_result_{i}.bin'), out_arr)
dump_txt_file(os.path.join(self.case_dir, f'cpu_result_{i}.txt'), out_arr)
i += 1
return outputs
def import_model(self, compiler, model_content, import_options):
compiler.import_ncnn(model_content[0], model_content[1], import_options)

View File

@ -16,17 +16,17 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
}
}
}

View File

@ -10,17 +10,17 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
}
}
}

View File

@ -34,11 +34,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.CodeAnalysis.Common": {
@ -62,8 +62,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="StyleCop.Analyzers rules with default action" Description="StyleCop.Analyzers with default action. Rules with IsEnabledByDefault = false are disabled." ToolsVersion="16.0">
<RuleSet Name="StyleCop.Analyzers rules with default action" Description="StyleCop.Analyzers with default action. Rules with IsEnabledByDefault = false are disabled." ToolsVersion="17.0">
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers.DocumentationRules">
<Rule Id="SA1600" Action="Hidden" />
<Rule Id="SA1601" Action="Hidden" />
@ -86,7 +86,7 @@
<Rule Id="SA1404" Action="Warning" />
<Rule Id="SA1405" Action="Warning" />
<Rule Id="SA1406" Action="Warning" />
<Rule Id="SA1407" Action="Warning" />
<Rule Id="SA1407" Action="None" />
<Rule Id="SA1408" Action="Warning" />
<Rule Id="SA1409" Action="None" />
<Rule Id="SA1410" Action="Warning" />
@ -177,6 +177,7 @@
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1309" Action="None" />
<Rule Id="SA1402" Action="None" />
<Rule Id="SA1407" Action="None" />
<Rule Id="SA1600" Action="Hidden" />
<Rule Id="SA1601" Action="Hidden" />
<Rule Id="SA1649" Action="None" />

View File

@ -27,11 +27,11 @@
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"requested": "[1.2.0-beta.507, )",
"resolved": "1.2.0-beta.507",
"contentHash": "/FtugDT66cKJJ+GGH7rNpG6UDrT4iIWz45M6lrXXHobDUFDHw+q5VgkbiR+6ffTO564ge7w6fQh/eoQhVdJO8Q==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
"StyleCop.Analyzers.Unstable": "1.2.0.507"
}
},
"Microsoft.AspNetCore.Mvc.Razor.Extensions": {
@ -169,8 +169,8 @@
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
"resolved": "1.2.0.507",
"contentHash": "gTY3IQdRqDJ4hbhSA3e/R48oE8b/OiKfvwkt1QdNVfrJK2gMHBV8ldaHJ885jxWZfllK66soa/sdcjh9bX49Tw=="
},
"System.Buffers": {
"type": "Transitive",