Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
f569dbc739
90 files changed
+3548
-1718
No files matched your search
@@ -161,10 +161,6 @@ jobs:
|
||||
displayName: 'CPU FuncTests'
|
||||
continueOnError: false
|
||||
|
||||
- script: $(BIN_DIR)/MklDnnBehaviorTests --gtest_output=xml:TEST-MklDnnBehaviorTests.xml
|
||||
displayName: 'MklDnnBehaviorTests'
|
||||
continueOnError: false
|
||||
|
||||
- script: |
|
||||
export DATA_PATH=$(MODELS_PATH)
|
||||
export MODELS_PATH=$(MODELS_PATH)
|
||||
|
||||
@@ -137,10 +137,6 @@ jobs:
|
||||
displayName: 'CPU FuncTests'
|
||||
continueOnError: false
|
||||
|
||||
- script: $(BIN_DIR)/MklDnnBehaviorTests --gtest_output=xml:TEST-MklDnnBehaviorTests.xml
|
||||
displayName: 'MklDnnBehaviorTests'
|
||||
continueOnError: false
|
||||
|
||||
- script: |
|
||||
export DATA_PATH=$(MODELS_PATH)
|
||||
export MODELS_PATH=$(MODELS_PATH)
|
||||
|
||||
@@ -162,16 +162,11 @@ jobs:
|
||||
|
||||
- script: |
|
||||
set PATH=$(TEST_ENV_PATH)
|
||||
rem $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke* --gtest_output=xml:TEST-cpuFuncTests.xml
|
||||
"$(IB_TESTCONSOLE)" $(BIN_DIR)\cpuFuncTests.exe --gtest_filter=*smoke*:-*CompareWithRefs/base_size=16_pre_nms_topn=100_post_nms_topn=100_nms_thresh=0.7_feat_stride=1_min_size=1_ratio* --gtest_output=xml:TEST-cpuFuncTests-IB.xml /testlevel=24
|
||||
displayName: 'CPU FuncTests - IB'
|
||||
continueOnError: false
|
||||
|
||||
- script: |
|
||||
set PATH=$(TEST_ENV_PATH)
|
||||
$(BIN_DIR)\MklDnnBehaviorTests --gtest_output=xml:TEST-MklDnnBehaviorTests.xml
|
||||
displayName: 'MklDnnBehaviorTests'
|
||||
continueOnError: false
|
||||
|
||||
# Add for gtest-parallel, it hangs now (CVS-33386)
|
||||
#python $(WORK_DIR)\gtest-parallel\gtest-parallel $(BIN_DIR)\MklDnnFunctionalTests --workers=$(WORKERS_NUMBER) --dump_json_test_results=MklDnnFunctionalTests.json --gtest_filter=*smoke* -- --gtest_print_time=1
|
||||
- script: |
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
name: IE Python Checks
|
||||
# TODO: add for IE API, wheels
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'inference-engine/ie_bridges/python/sample/**'
|
||||
- 'inference-engine/ie_bridges/python/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'inference-engine/ie_bridges/python/sample/**'
|
||||
- 'inference-engine/ie_bridges/python/**'
|
||||
jobs:
|
||||
linters:
|
||||
runs-on: ubuntu-18.04
|
||||
@@ -21,13 +21,55 @@ jobs:
|
||||
with:
|
||||
python-version: '3.6'
|
||||
- name: Install dependencies
|
||||
run: python -m pip install -r inference-engine/ie_bridges/python/sample/requirements_dev.txt
|
||||
- name: Run Flake
|
||||
run: python -m flake8 ./ --config=setup.cfg --show-source
|
||||
run: python -m pip install -r inference-engine/ie_bridges/python/requirements_dev.txt
|
||||
- name: Run Flake on samples
|
||||
run: python -m flake8 ./ --config=../setup.cfg
|
||||
working-directory: inference-engine/ie_bridges/python/sample
|
||||
- name: Run MyPy
|
||||
run: python -m mypy ./ --config-file ./setup.cfg --show-error-context --show-column-numbers --pretty
|
||||
working-directory: inference-engine/ie_bridges/python/sample
|
||||
- name: Create code style diff for samples
|
||||
if: failure()
|
||||
run: |
|
||||
python -m black -l 160 -S ./
|
||||
git diff > samples_diff.diff
|
||||
working-directory: inference-engine/ie_bridges/python/sample
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: samples_diff
|
||||
path: samples_diff.diff
|
||||
- name: Run Flake on src
|
||||
run: python -m flake8 ./ --config=../setup.cfg
|
||||
working-directory: inference-engine/ie_bridges/python/src
|
||||
- name: Create code style diff for Python src
|
||||
if: failure()
|
||||
run: |
|
||||
python -m black -l 160 -S ./
|
||||
git diff > src_diff.diff
|
||||
working-directory: inference-engine/ie_bridges/python/src
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: src_diff
|
||||
path: src_diff.diff
|
||||
- name: Run Flake on wheel
|
||||
run: python -m flake8 ./ --config=../setup.cfg
|
||||
working-directory: inference-engine/ie_bridges/python/wheel
|
||||
- name: Create code style diff for wheel
|
||||
if: failure()
|
||||
run: |
|
||||
python -m black -l 160 -S ./
|
||||
git diff > wheel_diff.diff
|
||||
working-directory: inference-engine/ie_bridges/python/wheel
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: wheel_diff
|
||||
path: wheel_diff.diff
|
||||
|
||||
- name: Run MyPy
|
||||
run: python -m mypy ./ --config-file ./setup.cfg
|
||||
working-directory: inference-engine/ie_bridges/python
|
||||
- name: Run Bandit
|
||||
run: python -m bandit -r ./ -f screen
|
||||
working-directory: inference-engine/ie_bridges/python/sample
|
||||
working-directory: inference-engine/ie_bridges/python
|
||||
|
||||
|
||||
@@ -2,36 +2,72 @@
|
||||
|
||||
**Versioned name**: *Sqrt-1*
|
||||
|
||||
**Category**: Arithmetic unary operation
|
||||
**Category**: Arithmetic unary operation
|
||||
|
||||
**Short description**: *Sqrt* performs element-wise square root operation with given tensor.
|
||||
**Short description**: Square root element-wise operation.
|
||||
|
||||
**Attributes**:
|
||||
**Detailed description**: *Sqrt* performs element-wise square root operation on a given input tensor `a`, as in the following mathematical formula, where `o` is the output tensor:
|
||||
|
||||
No attributes available.
|
||||
\f[
|
||||
o_{i} = \sqrt{a_{i}}
|
||||
\f]
|
||||
|
||||
If the input value is negative, then the result is undefined.\
|
||||
For integer element type the result is rounded (half up) to the nearest integer value.
|
||||
|
||||
**Attributes**: *Sqrt* operation has no attributes.
|
||||
|
||||
**Inputs**
|
||||
|
||||
* **1**: An tensor of type T. **Required.**
|
||||
* **1**: A tensor of type *T* and arbitrary shape. **Required.**
|
||||
|
||||
**Outputs**
|
||||
|
||||
* **1**: The result of element-wise sqrt operation. A tensor of type T.
|
||||
* **1**: The result of element-wise *Sqrt* operation. A tensor of type *T* and the same shape as input tensor.
|
||||
|
||||
**Types**
|
||||
|
||||
* *T*: any numeric type.
|
||||
|
||||
*Sqrt* does the following with the input tensor *a*:
|
||||
|
||||
\f[
|
||||
a_{i} = sqrt(a_{i})
|
||||
\f]
|
||||
|
||||
**Examples**
|
||||
|
||||
*Example 1*
|
||||
|
||||
```xml
|
||||
<layer ... type="Sqrt">
|
||||
<input>
|
||||
<port id="0">
|
||||
<dim>4</dim> <!-- float input values: [4.0, 7.0, 9.0, 10.0] -->
|
||||
</port>
|
||||
</input>
|
||||
<output>
|
||||
<port id="1">
|
||||
<dim>4</dim> <!-- float output values: [2.0, 2.6457512, 3.0, 3.1622777] -->
|
||||
</port>
|
||||
</output>
|
||||
</layer>
|
||||
```
|
||||
|
||||
*Example 2*
|
||||
|
||||
```xml
|
||||
<layer ... type="Sqrt">
|
||||
<input>
|
||||
<port id="0">
|
||||
<dim>4</dim> <!-- int input values: [4, 7, 9, 10] -->
|
||||
</port>
|
||||
</input>
|
||||
<output>
|
||||
<port id="1">
|
||||
<dim>4</dim> <!-- int output values: [2, 3, 3, 3] -->
|
||||
</port>
|
||||
</output>
|
||||
</layer>
|
||||
```
|
||||
|
||||
*Example 3*
|
||||
|
||||
```xml
|
||||
<layer ... type="Sqrt">
|
||||
<input>
|
||||
@@ -47,4 +83,4 @@ a_{i} = sqrt(a_{i})
|
||||
</port>
|
||||
</output>
|
||||
</layer>
|
||||
```
|
||||
```
|
||||
@@ -0,0 +1,2 @@
|
||||
[bandit]
|
||||
skips: B101
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
bandit
|
||||
black
|
||||
flake8
|
||||
flake8-annotations-complexity
|
||||
flake8-bandit
|
||||
flake8-broken-line
|
||||
flake8-bugbear
|
||||
flake8-class-attributes-order
|
||||
+15
-15
@@ -15,6 +15,7 @@ def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
@@ -31,7 +32,7 @@ def parse_args() -> argparse.Namespace:
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
args.add_argument('-nt', '--number_top', default=10, type=int, help='Optional. Number of top results.')
|
||||
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -39,7 +40,7 @@ def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
|
||||
@@ -51,7 +52,7 @@ def main():
|
||||
log.info(f'Loading the {args.device} configuration: {args.config}')
|
||||
ie.set_config({'CONFIG_FILE': args.config}, args.device)
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
@@ -63,7 +64,7 @@ def main():
|
||||
log.error('Sample supports only single output topologies')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
@@ -78,15 +79,15 @@ def main():
|
||||
# Get a number of classes recognized by a model
|
||||
num_of_classes = max(net.outputs[out_blob].shape)
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device, num_requests=num_of_input)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
input_data = []
|
||||
_, _, h, w = net.input_info[input_blob].input_data.shape
|
||||
|
||||
@@ -104,12 +105,12 @@ def main():
|
||||
|
||||
input_data.append(image)
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
log.info('Starting inference in asynchronous mode')
|
||||
for i in range(num_of_input):
|
||||
exec_net.requests[i].async_infer({input_blob: input_data[i]})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
@@ -136,7 +137,7 @@ def main():
|
||||
# Change a shape of a numpy.ndarray with results to get another one with one dimension
|
||||
probs = res.reshape(num_of_classes)
|
||||
# Get an array of args.number_top class IDs in descending order of probability
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top:][::-1]
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top :][::-1]
|
||||
|
||||
header = 'classid probability'
|
||||
header = header + ' label' if args.labels else header
|
||||
@@ -158,9 +159,8 @@ def main():
|
||||
if len(output_queue) == 0:
|
||||
break
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, '
|
||||
'for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
+15
-15
@@ -15,6 +15,7 @@ def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
@@ -25,7 +26,7 @@ def parse_args() -> argparse.Namespace:
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
args.add_argument('-nt', '--number_top', default=10, type=int, help='Optional. Number of top results.')
|
||||
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -33,11 +34,11 @@ def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
@@ -49,7 +50,7 @@ def main():
|
||||
log.error('Sample supports only single output topologies')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
@@ -62,15 +63,15 @@ def main():
|
||||
# Get a number of classes recognized by a model
|
||||
num_of_classes = max(net.outputs[out_blob].shape)
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
original_image = cv2.imread(args.input)
|
||||
image = original_image.copy()
|
||||
_, _, h, w = net.input_info[input_blob].input_data.shape
|
||||
@@ -84,11 +85,11 @@ def main():
|
||||
# Add N dimension to transform to NCHW
|
||||
image = np.expand_dims(image, axis=0)
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
log.info('Starting inference in synchronous mode')
|
||||
res = exec_net.infer(inputs={input_blob: image})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
@@ -98,7 +99,7 @@ def main():
|
||||
# Change a shape of a numpy.ndarray with results to get another one with one dimension
|
||||
probs = res.reshape(num_of_classes)
|
||||
# Get an array of args.number_top class IDs in descending order of probability
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top:][::-1]
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top :][::-1]
|
||||
|
||||
header = 'classid probability'
|
||||
header = header + ' label' if args.labels else header
|
||||
@@ -115,9 +116,8 @@ def main():
|
||||
log.info(f'{class_id}{probability_indent}{probs[class_id]:.7f}{label_indent}{label}')
|
||||
log.info('')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, '
|
||||
'for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ def param_to_string(metric) -> str:
|
||||
def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
|
||||
# ---------------------------Initialize inference engine core----------------------------------------------------------
|
||||
# ---------------------------Initialize inference engine core----------------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
|
||||
# ---------------------------Get metrics of available devices----------------------------------------------------------
|
||||
# ---------------------------Get metrics of available devices----------------------------------------------------------
|
||||
log.info('Available devices:')
|
||||
for device in ie.available_devices:
|
||||
log.info(f'{device} :')
|
||||
@@ -46,7 +46,7 @@ def main():
|
||||
log.info(f'\t\t{config_key}: {param_to_string(config_val)}')
|
||||
log.info('')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
@@ -30,7 +31,7 @@ def parse_args() -> argparse.Namespace:
|
||||
'is acceptable. The sample will look for a suitable plugin for device specified. '
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -38,7 +39,7 @@ def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
|
||||
@@ -50,7 +51,7 @@ def main():
|
||||
log.info(f'Loading the {args.device} configuration: {args.config}')
|
||||
ie.set_config({'CONFIG_FILE': args.config}, args.device)
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
@@ -62,7 +63,7 @@ def main():
|
||||
log.error('Sample supports only single output topologies')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
@@ -85,22 +86,22 @@ def main():
|
||||
net.reshape({input_blob: image.shape})
|
||||
log.info(f'Input shape after reshape: {net.input_info[input_blob].input_data.shape}')
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# This sample changes a network input layer shape instead of a image shape. See Step 4.
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# This sample changes a network input layer shape instead of a image shape. See Step 4.
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
log.info('Starting inference in synchronous mode')
|
||||
res = exec_net.infer(inputs={input_blob: image})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
@@ -126,8 +127,7 @@ def main():
|
||||
xmax = int(detection[5] * w)
|
||||
ymax = int(detection[6] * h)
|
||||
|
||||
log.info(f'Found: label = {label}, confidence = {confidence:.2f}, '
|
||||
f'coords = ({xmin}, {ymin}), ({xmax}, {ymax})')
|
||||
log.info(f'Found: label = {label}, confidence = {confidence:.2f}, ' f'coords = ({xmin}, {ymin}), ({xmax}, {ymax})')
|
||||
|
||||
# Draw a bounding box on a output image
|
||||
cv2.rectangle(output_image, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
|
||||
@@ -135,9 +135,8 @@ def main():
|
||||
cv2.imwrite('out.bmp', output_image)
|
||||
log.info('Image out.bmp was created!')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, '
|
||||
'for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
+25
-24
@@ -19,6 +19,7 @@ def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to a file with network weights.')
|
||||
@@ -29,7 +30,7 @@ def parse_args() -> argparse.Namespace:
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
args.add_argument('-nt', '--number_top', default=10, type=int, help='Optional. Number of top results.')
|
||||
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -40,7 +41,7 @@ def read_image(image_path: str) -> np.ndarray:
|
||||
# Try to open image as ubyte
|
||||
if image is None:
|
||||
with open(image_path, 'rb') as f:
|
||||
st.unpack('>4B', f.read(4)) # need to skip 4 bytes
|
||||
st.unpack('>4B', f.read(4)) # need to skip 4 bytes
|
||||
nimg = st.unpack('>I', f.read(4))[0] # number of images
|
||||
nrow = st.unpack('>I', f.read(4))[0] # number of rows
|
||||
ncolumn = st.unpack('>I', f.read(4))[0] # number of column
|
||||
@@ -78,7 +79,7 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
# add 1
|
||||
add_1_kernel_shape, add_1_kernel_length = shape_and_length([1, 20, 1, 1])
|
||||
add_1_kernel = ngraph.constant(
|
||||
weights[weights_offset:weights_offset + add_1_kernel_length].reshape(add_1_kernel_shape),
|
||||
weights[weights_offset : weights_offset + add_1_kernel_length].reshape(add_1_kernel_shape),
|
||||
)
|
||||
weights_offset += add_1_kernel_length
|
||||
add_1_node = ngraph.add(conv_1_node, add_1_kernel)
|
||||
@@ -89,7 +90,7 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
# convolution 2
|
||||
conv_2_kernel_shape, conv_2_kernel_length = shape_and_length([50, 20, 5, 5])
|
||||
conv_2_kernel = ngraph.constant(
|
||||
weights[weights_offset:weights_offset + conv_2_kernel_length].reshape(conv_2_kernel_shape),
|
||||
weights[weights_offset : weights_offset + conv_2_kernel_length].reshape(conv_2_kernel_shape),
|
||||
)
|
||||
weights_offset += conv_2_kernel_length
|
||||
conv_2_node = ngraph.convolution(maxpool_1_node, conv_2_kernel, [1, 1], padding_begin, padding_end, [1, 1])
|
||||
@@ -97,7 +98,7 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
# add 2
|
||||
add_2_kernel_shape, add_2_kernel_length = shape_and_length([1, 50, 1, 1])
|
||||
add_2_kernel = ngraph.constant(
|
||||
weights[weights_offset:weights_offset + add_2_kernel_length].reshape(add_2_kernel_shape),
|
||||
weights[weights_offset : weights_offset + add_2_kernel_length].reshape(add_2_kernel_shape),
|
||||
)
|
||||
weights_offset += add_2_kernel_length
|
||||
add_2_node = ngraph.add(conv_2_node, add_2_kernel)
|
||||
@@ -109,7 +110,8 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
reshape_1_dims, reshape_1_length = shape_and_length([2])
|
||||
# workaround to get int64 weights from float32 ndarray w/o unnecessary copying
|
||||
dtype_weights = np.frombuffer(
|
||||
weights[weights_offset:weights_offset + 2 * reshape_1_length], dtype=np.int64,
|
||||
weights[weights_offset : weights_offset + 2 * reshape_1_length],
|
||||
dtype=np.int64,
|
||||
)
|
||||
reshape_1_kernel = ngraph.constant(dtype_weights)
|
||||
weights_offset += 2 * reshape_1_length
|
||||
@@ -118,7 +120,7 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
# matmul 1
|
||||
matmul_1_kernel_shape, matmul_1_kernel_length = shape_and_length([500, 800])
|
||||
matmul_1_kernel = ngraph.constant(
|
||||
weights[weights_offset:weights_offset + matmul_1_kernel_length].reshape(matmul_1_kernel_shape),
|
||||
weights[weights_offset : weights_offset + matmul_1_kernel_length].reshape(matmul_1_kernel_shape),
|
||||
)
|
||||
weights_offset += matmul_1_kernel_length
|
||||
matmul_1_node = ngraph.matmul(reshape_1_node, matmul_1_kernel, False, True)
|
||||
@@ -126,7 +128,7 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
# add 3
|
||||
add_3_kernel_shape, add_3_kernel_length = shape_and_length([1, 500])
|
||||
add_3_kernel = ngraph.constant(
|
||||
weights[weights_offset:weights_offset + add_3_kernel_length].reshape(add_3_kernel_shape),
|
||||
weights[weights_offset : weights_offset + add_3_kernel_length].reshape(add_3_kernel_shape),
|
||||
)
|
||||
weights_offset += add_3_kernel_length
|
||||
add_3_node = ngraph.add(matmul_1_node, add_3_kernel)
|
||||
@@ -141,7 +143,7 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
# matmul 2
|
||||
matmul_2_kernel_shape, matmul_2_kernel_length = shape_and_length([10, 500])
|
||||
matmul_2_kernel = ngraph.constant(
|
||||
weights[weights_offset:weights_offset + matmul_2_kernel_length].reshape(matmul_2_kernel_shape),
|
||||
weights[weights_offset : weights_offset + matmul_2_kernel_length].reshape(matmul_2_kernel_shape),
|
||||
)
|
||||
weights_offset += matmul_2_kernel_length
|
||||
matmul_2_node = ngraph.matmul(reshape_2_node, matmul_2_kernel, False, True)
|
||||
@@ -149,7 +151,7 @@ def create_ngraph_function(args: argparse.Namespace) -> ngraph.impl.Function:
|
||||
# add 4
|
||||
add_4_kernel_shape, add_4_kernel_length = shape_and_length([1, 10])
|
||||
add_4_kernel = ngraph.constant(
|
||||
weights[weights_offset:weights_offset + add_4_kernel_length].reshape(add_4_kernel_shape),
|
||||
weights[weights_offset : weights_offset + add_4_kernel_length].reshape(add_4_kernel_shape),
|
||||
)
|
||||
weights_offset += add_4_kernel_length
|
||||
add_4_node = ngraph.add(matmul_2_node, add_4_kernel)
|
||||
@@ -167,16 +169,16 @@ def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation------------------------------
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation------------------------------
|
||||
log.info(f'Loading the network using ngraph function with weights from {args.model}')
|
||||
ngraph_function = create_ngraph_function(args)
|
||||
net = IENetwork(ngraph.impl.Function.to_capsule(ngraph_function))
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
@@ -189,15 +191,15 @@ def main():
|
||||
# Set a batch size to a equal number of input images
|
||||
net.batch_size = len(args.input)
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
n, c, h, w = net.input_info[input_blob].input_data.shape
|
||||
input_data = np.ndarray(shape=(n, c, h, w))
|
||||
|
||||
@@ -218,11 +220,11 @@ def main():
|
||||
|
||||
input_data[i] = image
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
log.info('Starting inference in synchronous mode')
|
||||
res = exec_net.infer(inputs={input_blob: input_data})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
@@ -233,7 +235,7 @@ def main():
|
||||
for i in range(n):
|
||||
probs = res[i]
|
||||
# Get an array of args.number_top class IDs in descending order of probability
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top:][::-1]
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top :][::-1]
|
||||
|
||||
header = 'classid probability'
|
||||
header = header + ' label' if args.labels else header
|
||||
@@ -250,9 +252,8 @@ def main():
|
||||
log.info(f'{class_id}{probability_indent}{probs[class_id]:.7f}{label_indent}{label}')
|
||||
log.info('')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, '
|
||||
'for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
+16
-17
@@ -15,6 +15,7 @@ def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
@@ -30,7 +31,7 @@ def parse_args() -> argparse.Namespace:
|
||||
'is acceptable. The sample will look for a suitable plugin for device specified. '
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -38,7 +39,7 @@ def main(): # noqa
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
|
||||
@@ -50,20 +51,20 @@ def main(): # noqa
|
||||
log.info(f'Loading the {args.device} configuration: {args.config}')
|
||||
ie.set_config({'CONFIG_FILE': args.config}, args.device)
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
|
||||
if len(net.input_info) != 1:
|
||||
log.error('The sample supports only single input topologies')
|
||||
return - 1
|
||||
return -1
|
||||
|
||||
if len(net.outputs) != 1 and not ('boxes' in net.outputs or 'labels' in net.outputs):
|
||||
log.error('The sample supports models with 1 output or with 2 with the names "boxes" and "labels"')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get name of input blob
|
||||
input_blob = next(iter(net.input_info))
|
||||
@@ -78,15 +79,15 @@ def main(): # noqa
|
||||
net.outputs['boxes'].precision = 'FP32'
|
||||
net.outputs['labels'].precision = 'U16'
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
original_image = cv2.imread(args.input)
|
||||
image = original_image.copy()
|
||||
_, _, net_h, net_w = net.input_info[input_blob].input_data.shape
|
||||
@@ -100,11 +101,11 @@ def main(): # noqa
|
||||
# Add N dimension to transform to NCHW
|
||||
image = np.expand_dims(image, axis=0)
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
log.info('Starting inference in synchronous mode')
|
||||
res = exec_net.infer(inputs={input_blob: image})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
@@ -139,8 +140,7 @@ def main(): # noqa
|
||||
xmax = int(xmax * w)
|
||||
ymax = int(ymax * h)
|
||||
|
||||
log.info(f'Found: label = {label}, confidence = {confidence:.2f}, '
|
||||
f'coords = ({xmin}, {ymin}), ({xmax}, {ymax})')
|
||||
log.info(f'Found: label = {label}, confidence = {confidence:.2f}, ' f'coords = ({xmin}, {ymin}), ({xmax}, {ymax})')
|
||||
|
||||
# Draw a bounding box on a output image
|
||||
cv2.rectangle(output_image, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
|
||||
@@ -148,9 +148,8 @@ def main(): # noqa
|
||||
cv2.imwrite('out.bmp', output_image)
|
||||
log.info('Image out.bmp created!')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, '
|
||||
'for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[flake8]
|
||||
max-line-length = 120
|
||||
max-parameters-amount = 8
|
||||
show_source = True
|
||||
docstring-convention = google
|
||||
enable-extensions=G
|
||||
|
||||
[pydocstyle]
|
||||
convention = google
|
||||
|
||||
[mypy]
|
||||
ignore_missing_imports = True
|
||||
+14
-14
@@ -15,6 +15,7 @@ def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
@@ -37,7 +38,7 @@ def parse_args() -> argparse.Namespace:
|
||||
help='Optional. Mean value of green channel for mean value subtraction in postprocessing.')
|
||||
args.add_argument('--mean_val_b', default=0, type=float,
|
||||
help='Optional. Mean value of blue channel for mean value subtraction in postprocessing.')
|
||||
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -45,7 +46,7 @@ def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
|
||||
@@ -57,7 +58,7 @@ def main():
|
||||
log.info(f'Loading the {args.device} configuration: {args.config}')
|
||||
ie.set_config({'CONFIG_FILE': args.config}, args.device)
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
@@ -69,7 +70,7 @@ def main():
|
||||
log.error('Sample supports only single output topologies')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
@@ -82,15 +83,15 @@ def main():
|
||||
# Set a batch size to a equal number of input images
|
||||
net.batch_size = len(args.input)
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
original_images = []
|
||||
|
||||
n, c, h, w = net.input_info[input_blob].input_data.shape
|
||||
@@ -109,11 +110,11 @@ def main():
|
||||
|
||||
input_data[i] = image
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
log.info('Starting inference in synchronous mode')
|
||||
res = exec_net.infer(inputs={input_blob: input_data})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
res = res[out_blob]
|
||||
|
||||
for i in range(n):
|
||||
@@ -136,9 +137,8 @@ def main():
|
||||
cv2.imwrite(f'out_{i}.bmp', output_image)
|
||||
log.info(f'Image out_{i}.bmp created!')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, '
|
||||
'for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
[flake8]
|
||||
filename = *.py, *.pyx
|
||||
max-line-length = 160
|
||||
ignore = E203
|
||||
max-parameters-amount = 8
|
||||
show_source = True
|
||||
docstring-convention = google
|
||||
enable-extensions = G
|
||||
per-file-ignores =
|
||||
*.pyx: E225, E226, E251, E999, E800, E265, E203, E266, E227, E211
|
||||
tests/*: S101, T001
|
||||
*__init__.py: F403, F405, F405
|
||||
|
||||
[pydocstyle]
|
||||
convention = google
|
||||
|
||||
[mypy]
|
||||
ignore_missing_imports = True
|
||||
disable_error_code = attr-defined
|
||||
show_column_numbers = True
|
||||
show_error_context = True
|
||||
show_absolute_path = True
|
||||
pretty = True
|
||||
@@ -1,3 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if sys.platform == "win32":
|
||||
if sys.platform == 'win32':
|
||||
# Installer, yum, pip installs openvino dlls to the different directories
|
||||
# and those paths need to be visible to the openvino modules
|
||||
#
|
||||
@@ -24,9 +25,9 @@ if sys.platform == "win32":
|
||||
if (3, 8) <= sys.version_info:
|
||||
os.add_dll_directory(os.path.abspath(lib_path))
|
||||
else:
|
||||
os.environ["PATH"] = os.path.abspath(lib_path) + ";" + os.environ["PATH"]
|
||||
os.environ['PATH'] = os.path.abspath(lib_path) + ';' + os.environ['PATH']
|
||||
|
||||
from .ie_api import *
|
||||
__all__ = ['IENetwork', "TensorDesc", "IECore", "Blob", "PreProcessInfo", "get_version"]
|
||||
__version__ = get_version()
|
||||
|
||||
__all__ = ['IENetwork', 'TensorDesc', 'IECore', 'Blob', 'PreProcessInfo', 'get_version']
|
||||
__version__ = get_version() # type: ignore
|
||||
@@ -6,49 +6,48 @@ from .cimport ie_api_impl_defs as C
|
||||
import numpy as np
|
||||
from enum import Enum
|
||||
|
||||
supported_precisions = ["FP32", "FP64", "FP16", "I64", "U64", "I32", "U32",
|
||||
"I16", "I4", "I8", "U16", "U4", "U8", "BOOL", "BIN", "BF16"]
|
||||
supported_precisions = ['FP32', 'FP64', 'FP16', 'I64', 'U64', 'I32', 'U32',
|
||||
'I16', 'I4', 'I8', 'U16', 'U4', 'U8', 'BOOL', 'BIN', 'BF16']
|
||||
|
||||
known_plugins = ['CPU', 'GPU', 'FPGA', 'MYRIAD', 'HETERO', 'HDDL', 'MULTI']
|
||||
|
||||
layout_int_to_str_map = {0: "ANY", 1: "NCHW", 2: "NHWC", 3: "NCDHW", 4: "NDHWC", 64: "OIHW", 95: "SCALAR", 96: "C",
|
||||
128: "CHW", 192: "HW", 193: "NC", 194: "CN", 200: "BLOCKED"}
|
||||
layout_int_to_str_map = {0: 'ANY', 1: 'NCHW', 2: 'NHWC', 3: 'NCDHW', 4: 'NDHWC', 64: 'OIHW', 95: 'SCALAR', 96: 'C',
|
||||
128: 'CHW', 192: 'HW', 193: 'NC', 194: 'CN', 200: 'BLOCKED'}
|
||||
|
||||
format_map = {
|
||||
'FP32' : np.float32,
|
||||
'FP64' : np.float64,
|
||||
'FP16' : np.float16,
|
||||
'I64' : np.int64,
|
||||
'U64' : np.uint64,
|
||||
'I32' : np.int32,
|
||||
'U32' : np.uint32,
|
||||
'I16' : np.int16,
|
||||
'U16' : np.uint16,
|
||||
'I4' : np.int8,
|
||||
'I8' : np.int8,
|
||||
'U4' : np.int8,
|
||||
'U8' : np.uint8,
|
||||
'BOOL' : np.uint8,
|
||||
'BIN' : np.int8,
|
||||
'BF16' : np.float16,
|
||||
}
|
||||
format_map = {'FP32' : np.float32,
|
||||
'FP64' : np.float64,
|
||||
'FP16' : np.float16,
|
||||
'I64' : np.int64,
|
||||
'U64' : np.uint64,
|
||||
'I32' : np.int32,
|
||||
'U32' : np.uint32,
|
||||
'I16' : np.int16,
|
||||
'U16' : np.uint16,
|
||||
'I4' : np.int8,
|
||||
'I8' : np.int8,
|
||||
'U4' : np.int8,
|
||||
'U8' : np.uint8,
|
||||
'BOOL' : np.uint8,
|
||||
'BIN' : np.int8,
|
||||
'BF16' : np.float16,
|
||||
}
|
||||
|
||||
layout_str_to_enum = {'ANY': C.Layout.ANY,
|
||||
"NHWC": C.Layout.NHWC,
|
||||
"NCHW": C.Layout.NCHW,
|
||||
"NCDHW": C.Layout.NCDHW,
|
||||
"NDHWC": C.Layout.NDHWC,
|
||||
"OIHW": C.Layout.OIHW,
|
||||
"GOIHW": C.Layout.GOIHW,
|
||||
"OIDHW": C.Layout.OIDHW,
|
||||
"GOIDHW": C.Layout.GOIDHW,
|
||||
"SCALAR": C.Layout.SCALAR,
|
||||
"C": C.Layout.C,
|
||||
"CHW": C.Layout.CHW,
|
||||
"HW": C.Layout.HW,
|
||||
"NC": C.Layout.NC,
|
||||
"CN": C.Layout.CN,
|
||||
"BLOCKED": C.Layout.BLOCKED
|
||||
'NHWC': C.Layout.NHWC,
|
||||
'NCHW': C.Layout.NCHW,
|
||||
'NCDHW': C.Layout.NCDHW,
|
||||
'NDHWC': C.Layout.NDHWC,
|
||||
'OIHW': C.Layout.OIHW,
|
||||
'GOIHW': C.Layout.GOIHW,
|
||||
'OIDHW': C.Layout.OIDHW,
|
||||
'GOIDHW': C.Layout.GOIDHW,
|
||||
'SCALAR': C.Layout.SCALAR,
|
||||
'C': C.Layout.C,
|
||||
'CHW': C.Layout.CHW,
|
||||
'HW': C.Layout.HW,
|
||||
'NC': C.Layout.NC,
|
||||
'CN': C.Layout.CN,
|
||||
'BLOCKED': C.Layout.BLOCKED
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -60,14 +60,19 @@ cdef c_map_to_dict(map[string, string] c_map):
|
||||
def get_version():
|
||||
return C.get_version().decode()
|
||||
|
||||
|
||||
## This class defines Tensor description
|
||||
cdef class TensorDesc:
|
||||
|
||||
def __eq__(self, other : TensorDesc):
|
||||
return self.layout == other.layout and self.precision == other.precision and self.dims == other.dims
|
||||
|
||||
def __ne__(self, other : TensorDesc):
|
||||
return self.layout != other.layout or self.precision != other.precision or self.dims != other.dims
|
||||
|
||||
def __deepcopy__(self, memodict={}):
|
||||
return TensorDesc(deepcopy(self.precision, memodict), deepcopy(self.dims, memodict), deepcopy(self.layout, memodict))
|
||||
|
||||
## Class constructor
|
||||
# @param precision: target memory precision
|
||||
# @param dims: target memory dimensions
|
||||
@@ -77,26 +82,32 @@ cdef class TensorDesc:
|
||||
if precision not in supported_precisions:
|
||||
raise ValueError(f"Unsupported precision {precision}! List of supported precisions: {supported_precisions}")
|
||||
self.impl = C.CTensorDesc(C.Precision.FromStr(precision.encode()), dims, layout_str_to_enum[layout])
|
||||
|
||||
## Shape (dimensions) of the TensorDesc object
|
||||
@property
|
||||
def dims(self):
|
||||
return self.impl.getDims()
|
||||
|
||||
@dims.setter
|
||||
def dims(self, dims_array : [list, tuple]):
|
||||
self.impl.setDims(dims_array)
|
||||
|
||||
## Precision of the TensorDesc object
|
||||
@property
|
||||
def precision(self):
|
||||
return self.impl.getPrecision().name().decode()
|
||||
|
||||
@precision.setter
|
||||
def precision(self, precision : str):
|
||||
if precision not in supported_precisions:
|
||||
raise ValueError(f"Unsupported precision {precision}! List of supported precisions: {supported_precisions}")
|
||||
self.impl.setPrecision(C.Precision.FromStr(precision.encode()))
|
||||
|
||||
## Layout of the TensorDesc object
|
||||
@property
|
||||
def layout(self):
|
||||
return layout_int_to_str_map[self.impl.getLayout()]
|
||||
|
||||
@layout.setter
|
||||
def layout(self, layout : str):
|
||||
if layout not in layout_str_to_enum.keys():
|
||||
@@ -148,17 +159,17 @@ cdef class Blob:
|
||||
self._ptr = C.make_shared_blob[int16_t](c_tensor_desc)
|
||||
elif precision == "Q78" or precision == "U16":
|
||||
self._ptr = C.make_shared_blob[uint16_t](c_tensor_desc)
|
||||
elif precision == "U8" or precision == "BOOL":
|
||||
elif precision == "U8" or precision == "BOOL":
|
||||
self._ptr = C.make_shared_blob[uint8_t](c_tensor_desc)
|
||||
elif precision == "I8" or precision == "BIN" or precision == "I4" or precision == "U4":
|
||||
elif precision == "I8" or precision == "BIN" or precision == "I4" or precision == "U4":
|
||||
self._ptr = C.make_shared_blob[int8_t](c_tensor_desc)
|
||||
elif precision == "I32":
|
||||
elif precision == "I32":
|
||||
self._ptr = C.make_shared_blob[int32_t](c_tensor_desc)
|
||||
elif precision == "U32":
|
||||
elif precision == "U32":
|
||||
self._ptr = C.make_shared_blob[uint32_t](c_tensor_desc)
|
||||
elif precision == "I64":
|
||||
elif precision == "I64":
|
||||
self._ptr = C.make_shared_blob[int64_t](c_tensor_desc)
|
||||
elif precision == "U64":
|
||||
elif precision == "U64":
|
||||
self._ptr = C.make_shared_blob[uint64_t](c_tensor_desc)
|
||||
else:
|
||||
raise AttributeError(f"Unsupported precision {precision} for blob")
|
||||
@@ -191,22 +202,22 @@ cdef class Blob:
|
||||
elif precision == "Q78" or precision == "U16":
|
||||
U16_array_memview = self._array_data
|
||||
self._ptr = C.make_shared_blob[uint16_t](c_tensor_desc, &U16_array_memview[0], U16_array_memview.shape[0])
|
||||
elif precision == "U8" or precision == "BOOL":
|
||||
elif precision == "U8" or precision == "BOOL":
|
||||
U8_array_memview = self._array_data
|
||||
self._ptr = C.make_shared_blob[uint8_t](c_tensor_desc, &U8_array_memview[0], U8_array_memview.shape[0])
|
||||
elif precision == "I8" or precision == "BIN" or precision == "I4" or precision == "U4":
|
||||
elif precision == "I8" or precision == "BIN" or precision == "I4" or precision == "U4":
|
||||
I8_array_memview = self._array_data
|
||||
self._ptr = C.make_shared_blob[int8_t](c_tensor_desc, &I8_array_memview[0], I8_array_memview.shape[0])
|
||||
elif precision == "I32":
|
||||
elif precision == "I32":
|
||||
I32_array_memview = self._array_data
|
||||
self._ptr = C.make_shared_blob[int32_t](c_tensor_desc, &I32_array_memview[0], I32_array_memview.shape[0])
|
||||
elif precision == "U32":
|
||||
elif precision == "U32":
|
||||
U32_array_memview = self._array_data
|
||||
self._ptr = C.make_shared_blob[uint32_t](c_tensor_desc, &U32_array_memview[0], U32_array_memview.shape[0])
|
||||
elif precision == "I64":
|
||||
elif precision == "I64":
|
||||
I64_array_memview = self._array_data
|
||||
self._ptr = C.make_shared_blob[int64_t](c_tensor_desc, &I64_array_memview[0], I64_array_memview.shape[0])
|
||||
elif precision == "U64":
|
||||
elif precision == "U64":
|
||||
U64_array_memview = self._array_data
|
||||
self._ptr = C.make_shared_blob[uint64_t](c_tensor_desc, &U64_array_memview[0], U64_array_memview.shape[0])
|
||||
else:
|
||||
@@ -301,7 +312,7 @@ cdef class IECore:
|
||||
raise Exception(f"Path to the weights {weights} doesn't exist or it's a directory")
|
||||
weights_ = weights.encode()
|
||||
|
||||
net.impl = self.impl.readNetwork(model_, weights_)
|
||||
net.impl = self.impl.readNetwork(model_, weights_)
|
||||
return net
|
||||
|
||||
## Loads a network that was read from the Intermediate Representation (IR) to the plugin with specified device name
|
||||
@@ -500,11 +511,13 @@ cdef class PreProcessChannel:
|
||||
property mean_value:
|
||||
def __get__(self):
|
||||
return deref(self._ptr).meanValue
|
||||
|
||||
def __set__(self, float mean_value):
|
||||
deref(self._ptr).meanValue = mean_value
|
||||
property std_scale:
|
||||
def __get__(self):
|
||||
return deref(self._ptr).stdScale
|
||||
|
||||
def __set__(self, float std_scale):
|
||||
deref(self._ptr).stdScale = std_scale
|
||||
property mean_data:
|
||||
@@ -512,6 +525,7 @@ cdef class PreProcessChannel:
|
||||
blob = Blob()
|
||||
blob._ptr = deref(self._ptr).meanData
|
||||
return blob
|
||||
|
||||
def __set__(self, Blob mean_data):
|
||||
deref(self._ptr).meanData = mean_data._ptr
|
||||
|
||||
@@ -519,7 +533,7 @@ cdef class PreProcessChannel:
|
||||
cdef class PreProcessInfo:
|
||||
def __cinit__(self):
|
||||
self._ptr = new CPreProcessInfo()
|
||||
self._user_data = True
|
||||
self._user_data = True
|
||||
|
||||
def __dealloc__(self):
|
||||
if self._user_data:
|
||||
@@ -581,7 +595,7 @@ cdef class PreProcessInfo:
|
||||
# ```
|
||||
@property
|
||||
def resize_algorithm(self):
|
||||
return ResizeAlgorithm(deref(self._ptr).getResizeAlgorithm())
|
||||
return ResizeAlgorithm(deref(self._ptr).getResizeAlgorithm())
|
||||
|
||||
@resize_algorithm.setter
|
||||
def resize_algorithm(self, alg : ResizeAlgorithm):
|
||||
@@ -757,18 +771,22 @@ cdef class CDataPtr:
|
||||
@property
|
||||
def name(self):
|
||||
return deref(self._ptr).getName().decode()
|
||||
|
||||
## Precision of the data object
|
||||
@property
|
||||
def precision(self):
|
||||
return deref(self._ptr).getPrecision().name().decode()
|
||||
|
||||
## Shape (dimensions) of the data object
|
||||
@property
|
||||
def shape(self):
|
||||
return deref(self._ptr).getDims()
|
||||
|
||||
## Layout of the data object
|
||||
@property
|
||||
def layout(self):
|
||||
return layout_int_to_str_map[deref(self._ptr).getLayout()]
|
||||
|
||||
## Checks if the current data object is resolved
|
||||
@property
|
||||
def initialized(self):
|
||||
@@ -810,7 +828,6 @@ cdef class ExecutableNetwork:
|
||||
res[name] = deepcopy(value.buffer)
|
||||
return res
|
||||
|
||||
|
||||
## Starts asynchronous inference for specified infer request.
|
||||
# Wraps `async_infer()` method of the `InferRequest` class.
|
||||
# @param request_id: Index of infer request to start inference
|
||||
@@ -877,6 +894,7 @@ cdef class ExecutableNetwork:
|
||||
data_ptr._ptr = in_.second
|
||||
inputs[in_.first.decode()] = data_ptr
|
||||
return inputs
|
||||
|
||||
## A dictionary that maps output layer names to CDataPtr objects
|
||||
@property
|
||||
def outputs(self):
|
||||
@@ -888,6 +906,7 @@ cdef class ExecutableNetwork:
|
||||
data_ptr._ptr = in_.second
|
||||
outputs[in_.first.decode()] = data_ptr
|
||||
return outputs
|
||||
|
||||
## Gets executable graph information from a device
|
||||
# @return An instance of `IENetwork`
|
||||
#
|
||||
@@ -1180,12 +1199,12 @@ cdef class InferRequest:
|
||||
cpdef get_perf_counts(self):
|
||||
cdef map[string, C.ProfileInfo] c_profile = deref(self.impl).getPerformanceCounts()
|
||||
profile = {}
|
||||
for l in c_profile:
|
||||
info = l.second
|
||||
for line in c_profile:
|
||||
info = line.second
|
||||
# TODO: add execution index. Check if unsigned int is properly converted to int in python.
|
||||
profile[l.first.decode()] = {"status": info.status.decode(), "exec_type": info.exec_type.decode(),
|
||||
"layer_type": info.layer_type.decode(), "real_time": info.real_time,
|
||||
"cpu_time": info.cpu_time, "execution_index": info.execution_index}
|
||||
profile[line.first.decode()] = {"status": info.status.decode(), "exec_type": info.exec_type.decode(),
|
||||
"layer_type": info.layer_type.decode(), "real_time": info.real_time,
|
||||
"cpu_time": info.cpu_time, "execution_index": info.execution_index}
|
||||
return profile
|
||||
|
||||
## A dictionary that maps input layer names to `numpy.ndarray`
|
||||
@@ -1294,8 +1313,7 @@ cdef class IENetwork:
|
||||
cdef string weights_
|
||||
if init_from_buffer:
|
||||
warnings.warn("Reading network using constructor is deprecated. "
|
||||
"Please, use IECore.read_network() method instead",
|
||||
DeprecationWarning)
|
||||
"Please, use IECore.read_network() method instead", DeprecationWarning)
|
||||
memcpy(xml_buffer, <char*> model, len(model))
|
||||
memcpy(bin_buffer, <uint8_t *> weights, len(weights))
|
||||
xml_buffer[len(model)] = b'\0'
|
||||
@@ -1304,8 +1322,7 @@ cdef class IENetwork:
|
||||
else:
|
||||
if model and weights:
|
||||
warnings.warn("Reading network using constructor is deprecated. "
|
||||
"Please, use IECore.read_network() method instead",
|
||||
DeprecationWarning)
|
||||
"Please, use IECore.read_network() method instead", DeprecationWarning)
|
||||
if not os.path.isfile(model):
|
||||
raise Exception(f"Path to the model {model} doesn't exist or it's a directory")
|
||||
if not os.path.isfile(weights):
|
||||
@@ -1389,7 +1406,6 @@ cdef class IENetwork:
|
||||
raise AttributeError(f"Invalid batch size {batch}! Batch size should be positive integer value")
|
||||
self.impl.setBatch(batch)
|
||||
|
||||
|
||||
## Marks any intermediate layer as output layer to retrieve the inference results from the specified layers.
|
||||
# @param outputs: List of layers to be set as model outputs. The list can contain strings with layer names to be set
|
||||
# as outputs or tuples with layer name as first element and output port id as second element.
|
||||
@@ -1405,13 +1421,13 @@ cdef class IENetwork:
|
||||
def add_outputs(self, outputs):
|
||||
if not isinstance(outputs, list):
|
||||
outputs = [outputs]
|
||||
for i, l in enumerate(outputs):
|
||||
if isinstance(l, str):
|
||||
self.impl.addOutput(l.encode(), 0)
|
||||
elif isinstance(l, tuple) and len(l) == 2:
|
||||
self.impl.addOutput(l[0].encode(), l[1])
|
||||
for i, line in enumerate(outputs):
|
||||
if isinstance(line, str):
|
||||
self.impl.addOutput(line.encode(), 0)
|
||||
elif isinstance(line, tuple) and len(line) == 2:
|
||||
self.impl.addOutput(line[0].encode(), line[1])
|
||||
else:
|
||||
raise TypeError(f"Incorrect type {type(l)} for layer to add at index {i}. "
|
||||
raise TypeError(f"Incorrect type {type(line)} for layer to add at index {i}. "
|
||||
"Expected string with layer name or tuple with two elements: layer name as "
|
||||
"first element and port id as second")
|
||||
|
||||
@@ -1447,7 +1463,7 @@ cdef class IENetwork:
|
||||
# net.reshape({input_layer: (n, c, h*2, w*2)})
|
||||
# ```
|
||||
def reshape(self, input_shapes: dict):
|
||||
cdef map[string, vector[size_t]] c_input_shapes;
|
||||
cdef map[string, vector[size_t]] c_input_shapes
|
||||
cdef vector[size_t] c_shape
|
||||
net_inputs = self.input_info
|
||||
for input, shape in input_shapes.items():
|
||||
@@ -1533,13 +1549,10 @@ cdef class BlobBuffer:
|
||||
|
||||
return precision_to_format[name].encode()
|
||||
|
||||
def to_numpy(self):
|
||||
def to_numpy(self):
|
||||
precision = deref(self.ptr).getTensorDesc().getPrecision()
|
||||
name = bytes(precision.name()).decode()
|
||||
if name == "FP16":
|
||||
name = bytes(precision.name()).decode()
|
||||
if name == "FP16":
|
||||
return np.asarray(self).view(dtype=np.float16)
|
||||
else:
|
||||
return np.asarray(self)
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if sys.platform == "win32":
|
||||
if sys.platform == 'win32':
|
||||
# Installer, yum, pip installs openvino dlls to the different directories
|
||||
# and those paths need to be visible to the openvino modules
|
||||
#
|
||||
@@ -24,7 +25,8 @@ if sys.platform == "win32":
|
||||
if (3, 8) <= sys.version_info:
|
||||
os.add_dll_directory(os.path.abspath(lib_path))
|
||||
else:
|
||||
os.environ["PATH"] = os.path.abspath(lib_path) + ";" + os.environ["PATH"]
|
||||
os.environ['PATH'] = os.path.abspath(lib_path) + ';' + os.environ['PATH']
|
||||
|
||||
from .offline_transformations_api import *
|
||||
|
||||
__all__ = ['ApplyMOCTransformations']
|
||||
+5
@@ -7,17 +7,22 @@ from ..inference_engine.ie_api cimport IENetwork
|
||||
from libcpp cimport bool
|
||||
from libcpp.string cimport string
|
||||
|
||||
|
||||
def ApplyMOCTransformations(IENetwork network, bool cf):
|
||||
C.ApplyMOCTransformations(network.impl, cf)
|
||||
|
||||
|
||||
def ApplyPOTTransformations(IENetwork network, string device):
|
||||
C.ApplyPOTTransformations(network.impl, device)
|
||||
|
||||
|
||||
def ApplyLowLatencyTransformation(IENetwork network):
|
||||
C.ApplyLowLatencyTransformation(network.impl)
|
||||
|
||||
|
||||
def ApplyPruningTransformation(IENetwork network):
|
||||
C.ApplyPruningTransformation(network.impl)
|
||||
|
||||
|
||||
def CheckAPI():
|
||||
C.CheckAPI()
|
||||
@@ -1,5 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from .test_utils_api import *
|
||||
|
||||
__all__ = ['CompareNetworks']
|
||||
@@ -8,6 +8,7 @@ from libcpp cimport bool
|
||||
from libcpp.string cimport string
|
||||
from libcpp.pair cimport pair
|
||||
|
||||
|
||||
def CompareNetworks(IENetwork lhs, IENetwork rhs):
|
||||
cdef pair[bool, string] c_pair
|
||||
c_pair = C.CompareNetworks(lhs.impl, rhs.impl)
|
||||
|
||||
@@ -10,6 +10,10 @@ py_modules =
|
||||
[options.package_data]
|
||||
mo = *.txt
|
||||
compression.configs.hardware = *.json
|
||||
mo.extensions.front.mxnet = *.json
|
||||
mo.extensions.front.onnx = *.json
|
||||
mo.extensions.front.tf = *.json
|
||||
mo.mo.front.caffe.proto = *.proto
|
||||
|
||||
[options.entry_points]
|
||||
console_scripts =
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
import errno
|
||||
import subprocess
|
||||
import subprocess # nosec
|
||||
import typing
|
||||
from pathlib import Path
|
||||
from shutil import copyfile
|
||||
from distutils.command.install import install
|
||||
@@ -18,94 +20,82 @@ from decouple import config
|
||||
|
||||
WHEEL_LIBS_INSTALL_DIR = os.path.join('openvino', 'libs')
|
||||
WHEEL_LIBS_PACKAGE = 'openvino.libs'
|
||||
PYTHON_VERSION = f"python{sys.version_info.major}.{sys.version_info.minor}"
|
||||
PYTHON_VERSION = f'python{sys.version_info.major}.{sys.version_info.minor}'
|
||||
|
||||
# The following variables can be defined in environment or .env file
|
||||
CMAKE_BUILD_DIR = config('CMAKE_BUILD_DIR', ".")
|
||||
CMAKE_BUILD_DIR = config('CMAKE_BUILD_DIR', '.')
|
||||
CORE_LIBS_DIR = config('CORE_LIBS_DIR', '')
|
||||
PLUGINS_LIBS_DIR = config('PLUGINS_LIBS_DIR', '')
|
||||
NGRAPH_LIBS_DIR = config('NGRAPH_LIBS_DIR', '')
|
||||
TBB_LIBS_DIR = config('TBB_LIBS_DIR', '')
|
||||
PY_PACKAGES_DIR = config('PY_PACKAGES_DIR', '')
|
||||
LIBS_RPATH = "$ORIGIN" if sys.platform == "linux" else "@loader_path"
|
||||
LIBS_RPATH = '$ORIGIN' if sys.platform == 'linux' else '@loader_path'
|
||||
|
||||
LIB_INSTALL_CFG = {
|
||||
"ie_libs": {
|
||||
'ie_libs': {
|
||||
'name': 'core',
|
||||
'prefix': 'libs.core',
|
||||
'install_dir': CORE_LIBS_DIR,
|
||||
'rpath': LIBS_RPATH,
|
||||
},
|
||||
"hetero_plugin": {
|
||||
'hetero_plugin': {
|
||||
'name': 'hetero',
|
||||
'prefix': 'libs.plugins',
|
||||
'install_dir': PLUGINS_LIBS_DIR,
|
||||
'rpath': LIBS_RPATH,
|
||||
},
|
||||
"gpu_plugin": {
|
||||
'gpu_plugin': {
|
||||
'name': 'gpu',
|
||||
'prefix': 'libs.plugins',
|
||||
'install_dir': PLUGINS_LIBS_DIR,
|
||||
'rpath': LIBS_RPATH,
|
||||
},
|
||||
"cpu_plugin": {
|
||||
'cpu_plugin': {
|
||||
'name': 'cpu',
|
||||
'prefix': 'libs.plugins',
|
||||
'install_dir': PLUGINS_LIBS_DIR,
|
||||
'rpath': LIBS_RPATH,
|
||||
},
|
||||
"multi_plugin": {
|
||||
'multi_plugin': {
|
||||
'name': 'multi',
|
||||
'prefix': 'libs.plugins',
|
||||
'install_dir': PLUGINS_LIBS_DIR,
|
||||
'rpath': LIBS_RPATH,
|
||||
},
|
||||
"myriad_plugin": {
|
||||
'myriad_plugin': {
|
||||
'name': 'myriad',
|
||||
'prefix': 'libs.plugins',
|
||||
'install_dir': PLUGINS_LIBS_DIR,
|
||||
'rpath': LIBS_RPATH,
|
||||
},
|
||||
"ngraph_libs": {
|
||||
'ngraph_libs': {
|
||||
'name': 'ngraph',
|
||||
'prefix': 'libs.ngraph',
|
||||
'install_dir': NGRAPH_LIBS_DIR,
|
||||
'rpath': LIBS_RPATH,
|
||||
},
|
||||
"tbb_libs": {
|
||||
'name': 'tbb',
|
||||
'prefix': 'libs.tbb',
|
||||
'install_dir': TBB_LIBS_DIR
|
||||
},
|
||||
'tbb_libs': {'name': 'tbb', 'prefix': 'libs.tbb', 'install_dir': TBB_LIBS_DIR},
|
||||
}
|
||||
|
||||
PY_INSTALL_CFG = {
|
||||
"ie_py": {
|
||||
'name': PYTHON_VERSION,
|
||||
'prefix': 'site-packages',
|
||||
'install_dir': PY_PACKAGES_DIR
|
||||
},
|
||||
"ngraph_py": {
|
||||
'name': f"pyngraph_{PYTHON_VERSION}",
|
||||
'prefix': 'site-packages',
|
||||
'install_dir': PY_PACKAGES_DIR
|
||||
},
|
||||
'ie_py': {'name': PYTHON_VERSION, 'prefix': 'site-packages', 'install_dir': PY_PACKAGES_DIR},
|
||||
'ngraph_py': {'name': f'pyngraph_{PYTHON_VERSION}', 'prefix': 'site-packages', 'install_dir': PY_PACKAGES_DIR},
|
||||
}
|
||||
|
||||
|
||||
class PrebuiltExtension(Extension):
|
||||
"""Initialize Extension"""
|
||||
|
||||
def __init__(self, name, sources, *args, **kwargs):
|
||||
if len(sources) != 1:
|
||||
nln = '\n'
|
||||
raise DistutilsSetupError(
|
||||
f"PrebuiltExtension can accept only one source, but got: {nln}{nln.join(sources)}"
|
||||
)
|
||||
raise DistutilsSetupError(f'PrebuiltExtension can accept only one source, but got: {nln}{nln.join(sources)}')
|
||||
super().__init__(name, sources, *args, **kwargs)
|
||||
|
||||
|
||||
class CustomBuild(build):
|
||||
"""Custom implementation of build_clib"""
|
||||
|
||||
def run(self):
|
||||
self.run_command('build_clib')
|
||||
build.run(self)
|
||||
@@ -113,6 +103,7 @@ class CustomBuild(build):
|
||||
|
||||
class CustomInstall(install):
|
||||
"""Enable build_clib during the installation"""
|
||||
|
||||
def run(self):
|
||||
self.run_command('build_clib')
|
||||
install.run(self)
|
||||
@@ -120,6 +111,7 @@ class CustomInstall(install):
|
||||
|
||||
class PrepareLibs(build_clib):
|
||||
"""Prepare prebuilt libraries"""
|
||||
|
||||
def run(self):
|
||||
self.configure(LIB_INSTALL_CFG)
|
||||
self.configure(PY_INSTALL_CFG)
|
||||
@@ -132,16 +124,13 @@ class PrepareLibs(build_clib):
|
||||
install_dir = comp_data.get('install_dir')
|
||||
if install_dir and not os.path.isabs(install_dir):
|
||||
install_dir = os.path.join(install_prefix, install_dir)
|
||||
self.announce(f"Installing {comp}", level=3)
|
||||
self.spawn(["cmake",
|
||||
"--install", CMAKE_BUILD_DIR,
|
||||
"--prefix", install_prefix,
|
||||
"--component", comp_data.get('name')])
|
||||
self.announce(f'Installing {comp}', level=3)
|
||||
self.spawn(['cmake', '--install', CMAKE_BUILD_DIR, '--prefix', install_prefix, '--component', comp_data.get('name')])
|
||||
# set rpath if applicable
|
||||
if sys.platform != "win32" and comp_data.get('rpath'):
|
||||
file_types = ["*.so"] if sys.platform == "linux" else ["*.dylib", "*.so"]
|
||||
for file in file_types:
|
||||
for path in Path(install_dir).glob(file):
|
||||
if sys.platform != 'win32' and comp_data.get('rpath'):
|
||||
file_types = ['*.so'] if sys.platform == 'linux' else ['*.dylib', '*.so']
|
||||
for file_type in file_types:
|
||||
for path in Path(install_dir).glob(file_type):
|
||||
set_rpath(comp_data['rpath'], path)
|
||||
|
||||
def generate_package(self, src_dirs):
|
||||
@@ -162,28 +151,28 @@ class PrepareLibs(build_clib):
|
||||
copyfile(file_path, dst_file)
|
||||
|
||||
if Path(package_dir).exists():
|
||||
self.announce(f"Adding {WHEEL_LIBS_PACKAGE} package", level=3)
|
||||
self.announce(f'Adding {WHEEL_LIBS_PACKAGE} package', level=3)
|
||||
packages.append(WHEEL_LIBS_PACKAGE)
|
||||
package_data.update({WHEEL_LIBS_PACKAGE: ['*']})
|
||||
|
||||
|
||||
class CopyExt(build_ext):
|
||||
"""Copy extension files to the build directory"""
|
||||
|
||||
def run(self):
|
||||
for extension in self.extensions:
|
||||
if not isinstance(extension, PrebuiltExtension):
|
||||
raise DistutilsSetupError(
|
||||
f"copy_ext can accept PrebuiltExtension only, but got {extension.name}")
|
||||
raise DistutilsSetupError(f'copy_ext can accept PrebuiltExtension only, but got {extension.name}')
|
||||
src = extension.sources[0]
|
||||
dst = self.get_ext_fullpath(extension.name)
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
# setting relative path to find dlls
|
||||
if sys.platform != "win32":
|
||||
if sys.platform != 'win32':
|
||||
rpath = os.path.relpath(get_package_dir(PY_INSTALL_CFG), os.path.dirname(src))
|
||||
if sys.platform == "linux":
|
||||
rpath = os.path.join("$ORIGIN", rpath, WHEEL_LIBS_INSTALL_DIR)
|
||||
elif sys.platform == "darwin":
|
||||
rpath = os.path.join("@loader_path", rpath, WHEEL_LIBS_INSTALL_DIR)
|
||||
if sys.platform == 'linux':
|
||||
rpath = os.path.join('$ORIGIN', rpath, WHEEL_LIBS_INSTALL_DIR)
|
||||
elif sys.platform == 'darwin':
|
||||
rpath = os.path.join('@loader_path', rpath, WHEEL_LIBS_INSTALL_DIR)
|
||||
set_rpath(rpath, src)
|
||||
|
||||
copy_file(src, dst, verbose=self.verbose, dry_run=self.dry_run)
|
||||
@@ -193,7 +182,7 @@ def is_tool(name):
|
||||
"""Check if the command-line tool is available"""
|
||||
try:
|
||||
devnull = subprocess.DEVNULL
|
||||
subprocess.Popen([name], stdout=devnull, stderr=devnull).communicate()
|
||||
subprocess.Popen([name], stdout=devnull, stderr=devnull).communicate() # nosec
|
||||
except OSError as error:
|
||||
if error.errno == errno.ENOENT:
|
||||
return False
|
||||
@@ -202,80 +191,81 @@ def is_tool(name):
|
||||
|
||||
def remove_rpath(file_path):
|
||||
"""
|
||||
Remove rpath from binaries
|
||||
:param file_path: binary path
|
||||
:type file_path: pathlib.Path
|
||||
Remove rpath from binaries
|
||||
:param file_path: binary path
|
||||
:type file_path: pathlib.Path
|
||||
"""
|
||||
if sys.platform == "darwin":
|
||||
cmd = f'otool -l {file_path} ' \
|
||||
f'| grep LC_RPATH -A3 ' \
|
||||
f'| grep -o "path.*" ' \
|
||||
f'| cut -d " " -f2 ' \
|
||||
f'| xargs -I{{}} install_name_tool -delete_rpath {{}} {file_path}'
|
||||
if os.WEXITSTATUS(os.system(cmd)) != 0:
|
||||
sys.exit(f"Could not remove rpath for {file_path}")
|
||||
if sys.platform == 'darwin':
|
||||
cmd = (
|
||||
f'otool -l {file_path} ' # noqa: P103
|
||||
f'| grep LC_RPATH -A3 '
|
||||
f'| grep -o "path.*" '
|
||||
f'| cut -d " " -f2 '
|
||||
f'| xargs -I{{}} install_name_tool -delete_rpath {{}} {file_path}'
|
||||
)
|
||||
if os.WEXITSTATUS(os.system(cmd)) != 0: # nosec
|
||||
sys.exit(f'Could not remove rpath for {file_path}')
|
||||
else:
|
||||
sys.exit(f"Unsupported platform: {sys.platform}")
|
||||
sys.exit(f'Unsupported platform: {sys.platform}')
|
||||
|
||||
|
||||
def set_rpath(rpath, executable):
|
||||
"""Setting rpath for linux and macOS libraries"""
|
||||
print(f"Setting rpath {rpath} for {executable}")
|
||||
cmd = ""
|
||||
rpath_tool = ""
|
||||
if sys.platform == "linux":
|
||||
rpath_tool = "patchelf"
|
||||
cmd = [rpath_tool, "--set-rpath", rpath, executable]
|
||||
elif sys.platform == "darwin":
|
||||
rpath_tool = "install_name_tool"
|
||||
cmd = [rpath_tool, "-add_rpath", rpath, executable]
|
||||
print(f'Setting rpath {rpath} for {executable}') # noqa: T001
|
||||
cmd = []
|
||||
rpath_tool = ''
|
||||
if sys.platform == 'linux':
|
||||
rpath_tool = 'patchelf'
|
||||
cmd = [rpath_tool, '--set-rpath', rpath, executable]
|
||||
elif sys.platform == 'darwin':
|
||||
rpath_tool = 'install_name_tool'
|
||||
cmd = [rpath_tool, '-add_rpath', rpath, executable]
|
||||
else:
|
||||
sys.exit(f"Unsupported platform: {sys.platform}")
|
||||
sys.exit(f'Unsupported platform: {sys.platform}')
|
||||
|
||||
if is_tool(rpath_tool):
|
||||
if sys.platform == "darwin":
|
||||
if sys.platform == 'darwin':
|
||||
remove_rpath(executable)
|
||||
ret_info = subprocess.run(cmd, check=True)
|
||||
ret_info = subprocess.run(cmd, check=True, shell=False) # nosec
|
||||
if ret_info.returncode != 0:
|
||||
sys.exit(f"Could not set rpath: {rpath} for {executable}")
|
||||
sys.exit(f'Could not set rpath: {rpath} for {executable}')
|
||||
else:
|
||||
sys.exit(f"Could not found {rpath_tool} on the system, "
|
||||
f"please make sure that this tool is installed")
|
||||
sys.exit(f'Could not found {rpath_tool} on the system, ' f'please make sure that this tool is installed')
|
||||
|
||||
|
||||
def find_prebuilt_extensions(search_dirs):
|
||||
"""collect prebuilt python extensions"""
|
||||
extensions = []
|
||||
ext_pattern = ""
|
||||
if sys.platform == "linux":
|
||||
ext_pattern = "**/*.so"
|
||||
elif sys.platform == "win32":
|
||||
ext_pattern = "**/*.pyd"
|
||||
elif sys.platform == "darwin":
|
||||
ext_pattern = "**/*.so"
|
||||
ext_pattern = ''
|
||||
if sys.platform == 'linux':
|
||||
ext_pattern = '**/*.so'
|
||||
elif sys.platform == 'win32':
|
||||
ext_pattern = '**/*.pyd'
|
||||
elif sys.platform == 'darwin':
|
||||
ext_pattern = '**/*.so'
|
||||
for base_dir in search_dirs:
|
||||
for path in Path(base_dir).glob(ext_pattern):
|
||||
relpath = path.relative_to(base_dir)
|
||||
if relpath.parent != ".":
|
||||
if relpath.parent != '.':
|
||||
package_names = str(relpath.parent).split(os.path.sep)
|
||||
else:
|
||||
package_names = []
|
||||
package_names.append(path.name.split(".", 1)[0])
|
||||
name = ".".join(package_names)
|
||||
package_names.append(path.name.split('.', 1)[0])
|
||||
name = '.'.join(package_names)
|
||||
extensions.append(PrebuiltExtension(name, sources=[str(path)]))
|
||||
return extensions
|
||||
|
||||
|
||||
def get_description(desc_file_path):
|
||||
"""read description from README.md"""
|
||||
with open(desc_file_path, "r", encoding="utf-8") as fstream:
|
||||
with open(desc_file_path, 'r', encoding='utf-8') as fstream:
|
||||
description = fstream.read()
|
||||
return description
|
||||
|
||||
|
||||
def get_dependencies(requirements_file_path):
|
||||
"""read dependencies from requirements.txt"""
|
||||
with open(requirements_file_path, "r", encoding="utf-8") as fstream:
|
||||
with open(requirements_file_path, 'r', encoding='utf-8') as fstream:
|
||||
dependencies = fstream.read()
|
||||
return dependencies
|
||||
|
||||
@@ -299,7 +289,7 @@ def get_package_dir(install_cfg):
|
||||
Get python package path based on config
|
||||
All the packages should be located in one directory
|
||||
"""
|
||||
py_package_path = ""
|
||||
py_package_path = ''
|
||||
dirs = get_dir_list(install_cfg)
|
||||
if len(dirs) != 0:
|
||||
# setup.py support only one package directory, all modules should be located there
|
||||
@@ -307,17 +297,17 @@ def get_package_dir(install_cfg):
|
||||
return py_package_path
|
||||
|
||||
|
||||
platforms = ["linux", "win32", "darwin"]
|
||||
platforms = ['linux', 'win32', 'darwin']
|
||||
if not any(pl in sys.platform for pl in platforms):
|
||||
sys.exit("Unsupported platform: {}, expected: {}".format(sys.platform, "linux, win32, darwin"))
|
||||
sys.exit(f'Unsupported platform: {sys.platform}, expected: linux, win32, darwin')
|
||||
|
||||
# copy license file into the build directory
|
||||
package_license = config('WHEEL_LICENSE', '')
|
||||
if os.path.exists(package_license):
|
||||
copyfile(package_license, "LICENSE")
|
||||
copyfile(package_license, 'LICENSE')
|
||||
|
||||
packages = find_namespace_packages(','.join(get_dir_list(PY_INSTALL_CFG)))
|
||||
package_data = {}
|
||||
package_data: typing.Dict[str, list] = {}
|
||||
|
||||
setup(
|
||||
version=config('WHEEL_VERSION', '0.0.0'),
|
||||
@@ -326,16 +316,16 @@ setup(
|
||||
license=config('WHEEL_LICENCE_TYPE', 'OSI Approved :: Apache Software License'),
|
||||
author=config('WHEEL_AUTHOR', 'Intel Corporation'),
|
||||
description=config('WHEEL_DESC', 'Inference Engine Python* API'),
|
||||
install_requires=get_dependencies(config('WHEEL_REQUIREMENTS', "requirements.txt")),
|
||||
install_requires=get_dependencies(config('WHEEL_REQUIREMENTS', 'requirements.txt')),
|
||||
long_description=get_description(config('WHEEL_OVERVIEW', 'pypi_overview.md')),
|
||||
long_description_content_type="text/markdown",
|
||||
long_description_content_type='text/markdown',
|
||||
download_url=config('WHEEL_DOWNLOAD_URL', 'https://github.com/openvinotoolkit/openvino/tags'),
|
||||
url=config('WHEEL_URL', 'https://docs.openvinotoolkit.org/latest/index.html'),
|
||||
cmdclass={
|
||||
"build": CustomBuild,
|
||||
"install": CustomInstall,
|
||||
"build_clib": PrepareLibs,
|
||||
"build_ext": CopyExt,
|
||||
'build': CustomBuild,
|
||||
'install': CustomInstall,
|
||||
'build_clib': PrepareLibs,
|
||||
'build_ext': CopyExt,
|
||||
},
|
||||
ext_modules=find_prebuilt_extensions(get_dir_list(PY_INSTALL_CFG)),
|
||||
packages=packages,
|
||||
|
||||
@@ -205,11 +205,16 @@ DECLARE_CONFIG_KEY(CPU_THREADS_NUM);
|
||||
* @brief The name for setting CPU affinity per thread option.
|
||||
*
|
||||
* It is passed to Core::SetConfig(), this option should be used with values:
|
||||
* PluginConfigParams::YES (pinning threads to cores, best for static benchmarks),
|
||||
* PluginConfigParams::NUMA (pinning threads to NUMA nodes, best for real-life, contented cases)
|
||||
* this is TBB-specific knob, and the only pinning option (beyond 'NO', below) on the Windows*
|
||||
* PluginConfigParams::NO (no pinning for CPU inference threads)
|
||||
* All settings are ignored, if the OpenVINO compiled with OpenMP threading and any affinity-related OpenMP's
|
||||
* PluginConfigParams::YES, which is default on the conventional CPUs (pinning threads to cores, best for static benchmarks),
|
||||
*
|
||||
* the following options are implemented only for the TBB as a threading option
|
||||
* PluginConfigParams::NUMA (pinning threads to NUMA nodes, best for real-life, contented cases)
|
||||
* on the Windows and MacOS* this option behaves as YES
|
||||
* PluginConfigParams::HYBRID_AWARE (let the runtime to do pinning to the cores types, e.g. prefer the "big" cores for latency tasks)
|
||||
* on the hybrid CPUs this option is default
|
||||
*
|
||||
* Also, the settings are ignored, if the OpenVINO compiled with OpenMP and any affinity-related OpenMP's
|
||||
* environment variable is set (as affinity is configured explicitly)
|
||||
*/
|
||||
DECLARE_CONFIG_KEY(CPU_BIND_THREAD);
|
||||
|
||||
@@ -104,14 +104,16 @@ Options:
|
||||
estimations the number of streams should be set to 1.
|
||||
-nthreads "<integer>" Optional. Number of threads to use for inference on the CPU (including HETERO and MULTI cases).
|
||||
-enforcebf16="<true/false>" Optional. By default floating point operations execution in bfloat16 precision are enforced if supported by platform.
|
||||
'true' - enable bfloat16 regardless of platform support
|
||||
'false' - disable bfloat16 regardless of platform support.
|
||||
-pin "YES"/"NO"/"NUMA" Optional. Enable threads->cores ("YES", default), threads->(NUMA)nodes ("NUMA") or completely disable ("NO") CPU threads pinning for CPU-involved inference.
|
||||
-pin "YES"/"HYBRID_AWARE"/"NUMA"/"NO"
|
||||
Optional. Explicit inference threads binding options (leave empty to let the OpenVINO to make a choice):
|
||||
enabling threads->cores pinning ("YES", which is already default for a conventional CPU),
|
||||
letting the runtime to decide on the threads->different core types ("HYBRID_AWARE", which is default on the hybrid CPUs)
|
||||
threads->(NUMA)nodes ("NUMA") or
|
||||
completely disable ("NO") CPU inference threads pinning.
|
||||
-ip "U8"/"FP16"/"FP32" Optional. Specifies precision for all input layers of the network.
|
||||
-op "U8"/"FP16"/"FP32" Optional. Specifies precision for all output layers of the network.
|
||||
-iop Optional. Specifies precision for input and output layers by name. Example: -iop "input:FP16, output:FP16". Notice that quotes are required. Overwrites precision from ip and op options for specified layers.
|
||||
|
||||
|
||||
Statistics dumping options:
|
||||
-report_type "<type>" Optional. Enable collecting statistics report. "no_counters" report contains configuration options specified, resulting FPS and latency. "average_counters" report extends "no_counters" report and additionally includes average PM counters values for each layer from the network. "detailed_counters" report extends "average_counters" report and additionally includes per-layer PM counters and latency for each executed infer request.
|
||||
-report_folder Optional. Path to a folder where statistics report is stored.
|
||||
|
||||
@@ -73,10 +73,12 @@ static const char batch_size_message[] = "Optional. Batch size value. If not spe
|
||||
"Intermediate Representation.";
|
||||
|
||||
// @brief message for CPU threads pinning option
|
||||
static const char infer_threads_pinning_message[] = "Optional. Enable threads->cores (\"YES\", default), threads->(NUMA)nodes (\"NUMA\") "
|
||||
"or completely disable (\"NO\") "
|
||||
"CPU threads pinning for CPU-involved inference.";
|
||||
|
||||
static const char infer_threads_pinning_message[] =
|
||||
"Optional. Explicit inference threads binding options (leave empty to let the OpenVINO to make a choice):\n"
|
||||
"\t\t\t\tenabling threads->cores pinning(\"YES\", which is already default for any conventional CPU), \n"
|
||||
"\t\t\t\tletting the runtime to decide on the threads->different core types(\"HYBRID_AWARE\", which is default on the hybrid CPUs) \n"
|
||||
"\t\t\t\tthreads->(NUMA)nodes(\"NUMA\") or \n"
|
||||
"\t\t\t\tcompletely disable(\"NO\") CPU inference threads pinning";
|
||||
// @brief message for stream_output option
|
||||
static const char stream_output_message[] = "Optional. Print progress as a plain text. When specified, an interactive progress bar is "
|
||||
"replaced with a "
|
||||
@@ -187,7 +189,7 @@ DEFINE_bool(enforcebf16, false, enforce_bf16_message);
|
||||
DEFINE_uint32(b, 0, batch_size_message);
|
||||
|
||||
// @brief Enable plugin messages
|
||||
DEFINE_string(pin, "YES", infer_threads_pinning_message);
|
||||
DEFINE_string(pin, "", infer_threads_pinning_message);
|
||||
|
||||
/// @brief Enables multiline text output instead of progress bar
|
||||
DEFINE_bool(stream_output, false, stream_output_message);
|
||||
@@ -264,7 +266,7 @@ static void showUsage() {
|
||||
std::cout << " -nstreams \"<integer>\" " << infer_num_streams_message << std::endl;
|
||||
std::cout << " -nthreads \"<integer>\" " << infer_num_threads_message << std::endl;
|
||||
std::cout << " -enforcebf16=<true/false> " << enforce_bf16_message << std::endl;
|
||||
std::cout << " -pin \"YES\"/\"NO\"/\"NUMA\" " << infer_threads_pinning_message << std::endl;
|
||||
std::cout << " -pin \"YES\"/\"HYBRID_AWARE\"/\"NO\"/\"NUMA\" " << infer_threads_pinning_message << std::endl;
|
||||
std::cout << std::endl << " Statistics dumping options:" << std::endl;
|
||||
std::cout << " -report_type \"<type>\" " << report_type_message << std::endl;
|
||||
std::cout << " -report_folder " << report_folder_message << std::endl;
|
||||
|
||||
@@ -267,9 +267,6 @@ int main(int argc, char* argv[]) {
|
||||
if ((device_name.find("MULTI") != std::string::npos) && (device_name.find("GPU") != std::string::npos)) {
|
||||
slog::warn << "Turn off threads pinning for " << device << " device since multi-scenario with GPU device is used." << slog::endl;
|
||||
device_config[CONFIG_KEY(CPU_BIND_THREAD)] = CONFIG_VALUE(NO);
|
||||
} else {
|
||||
// set to default value
|
||||
device_config[CONFIG_KEY(CPU_BIND_THREAD)] = FLAGS_pin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
set (TARGET_NAME "inference_engine")
|
||||
|
||||
if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO")
|
||||
find_package(TBBBIND_2_4)
|
||||
find_package(TBBBIND_2_4 QUIET)
|
||||
if (TBBBIND_2_4_FOUND)
|
||||
message(STATUS "Static tbbbind_2_4 package was found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file (GLOB LIBRARY_SRC
|
||||
|
||||
@@ -90,9 +90,9 @@ bool checkOpenMpEnvVars(bool includeOMPNumThreads) {
|
||||
#if defined(__APPLE__)
|
||||
// for Linux and Windows the getNumberOfCPUCores (that accounts only for physical cores) implementation is OS-specific
|
||||
// (see cpp files in corresponding folders), for __APPLE__ it is default :
|
||||
int getNumberOfCPUCores() { return parallel_get_max_threads();}
|
||||
int getNumberOfCPUCores(bool) { return parallel_get_max_threads();}
|
||||
#if !((IE_THREAD == IE_THREAD_TBB) || (IE_THREAD == IE_THREAD_TBB_AUTO))
|
||||
std::vector<int> getAvailableNUMANodes() { return {0}; }
|
||||
std::vector<int> getAvailableNUMANodes() { return {-1}; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -100,6 +100,15 @@ std::vector<int> getAvailableNUMANodes() { return {0}; }
|
||||
std::vector<int> getAvailableNUMANodes() {
|
||||
return custom::info::numa_nodes();
|
||||
}
|
||||
// this is impl only with the TBB
|
||||
std::vector<int> getAvailableCoresTypes() {
|
||||
return custom::info::core_types();
|
||||
}
|
||||
#else
|
||||
// as the core types support exists only with the TBB, the fallback is same for any other threading API
|
||||
std::vector<int> getAvailableCoresTypes() {
|
||||
return {-1};
|
||||
}
|
||||
#endif
|
||||
|
||||
std::exception_ptr& CurrentException() {
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <sched.h>
|
||||
#include "ie_system_conf.h"
|
||||
#include "ie_parallel.hpp"
|
||||
#include "ie_common.h"
|
||||
#include <numeric>
|
||||
#include <sched.h>
|
||||
|
||||
#include "ie_common.h"
|
||||
#include "ie_system_conf.h"
|
||||
#include "threading/ie_parallel_custom_arena.hpp"
|
||||
|
||||
|
||||
namespace InferenceEngine {
|
||||
@@ -61,7 +62,7 @@ std::vector<int> getAvailableNUMANodes() {
|
||||
return nodes;
|
||||
}
|
||||
#endif
|
||||
int getNumberOfCPUCores() {
|
||||
int getNumberOfCPUCores(bool bigCoresOnly) {
|
||||
unsigned numberOfProcessors = cpu._processors;
|
||||
unsigned totalNumberOfCpuCores = cpu._cores;
|
||||
IE_ASSERT(totalNumberOfCpuCores != 0);
|
||||
@@ -81,7 +82,16 @@ int getNumberOfCPUCores() {
|
||||
}
|
||||
}
|
||||
}
|
||||
return CPU_COUNT(¤tCoreSet);
|
||||
int phys_cores = CPU_COUNT(¤tCoreSet);
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
|
||||
auto core_types = custom::info::core_types();
|
||||
if (bigCoresOnly && core_types.size() > 1) /*Hybrid CPU*/ {
|
||||
phys_cores = custom::info::default_concurrency(custom::task_arena::constraints{}
|
||||
.set_core_type(core_types.back())
|
||||
.set_max_threads_per_core(1));
|
||||
}
|
||||
#endif
|
||||
return phys_cores;
|
||||
}
|
||||
|
||||
} // namespace InferenceEngine
|
||||
@@ -10,10 +10,10 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "ie_system_conf.h"
|
||||
#include "ie_parallel.hpp"
|
||||
#include "threading/ie_parallel_custom_arena.hpp"
|
||||
|
||||
namespace InferenceEngine {
|
||||
int getNumberOfCPUCores() {
|
||||
int getNumberOfCPUCores(bool bigCoresOnly) {
|
||||
const int fallback_val = parallel_get_max_threads();
|
||||
DWORD sz = 0;
|
||||
// querying the size of the resulting structure, passing the nullptr for the buffer
|
||||
@@ -32,12 +32,21 @@ int getNumberOfCPUCores() {
|
||||
offset += reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX>(ptr.get() + offset)->Size;
|
||||
phys_cores++;
|
||||
} while (offset < sz);
|
||||
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
|
||||
auto core_types = custom::info::core_types();
|
||||
if (bigCoresOnly && core_types.size() > 1) /*Hybrid CPU*/ {
|
||||
phys_cores = custom::info::default_concurrency(custom::task_arena::constraints{}
|
||||
.set_core_type(core_types.back())
|
||||
.set_max_threads_per_core(1));
|
||||
}
|
||||
#endif
|
||||
return phys_cores;
|
||||
}
|
||||
|
||||
#if !(IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
|
||||
// OMP/SEQ threading on the Windows doesn't support NUMA
|
||||
std::vector<int> getAvailableNUMANodes() { return std::vector<int>(1, 0); }
|
||||
std::vector<int> getAvailableNUMANodes() { return {-1}; }
|
||||
#endif
|
||||
|
||||
} // namespace InferenceEngine
|
||||
@@ -32,14 +32,14 @@ struct CPUStreamsExecutor::Impl {
|
||||
int _ncpus = 0;
|
||||
int _threadBindingStep = 0;
|
||||
int _offset = 0;
|
||||
Observer(tbb::task_arena& arena,
|
||||
Observer(custom::task_arena& arena,
|
||||
CpuSet mask,
|
||||
int ncpus,
|
||||
const int streamId,
|
||||
const int threadsPerStream,
|
||||
const int threadBindingStep,
|
||||
const int threadBindingOffset) :
|
||||
tbb::task_scheduler_observer(arena),
|
||||
tbb::task_scheduler_observer(static_cast<tbb::task_arena&>(arena)),
|
||||
_mask{std::move(mask)},
|
||||
_ncpus(ncpus),
|
||||
_threadBindingStep(threadBindingStep),
|
||||
@@ -71,19 +71,30 @@ struct CPUStreamsExecutor::Impl {
|
||||
((_impl->_config._streams + _impl->_usedNumaNodes.size() - 1)/_impl->_usedNumaNodes.size()))
|
||||
: _impl->_usedNumaNodes.at(_streamId % _impl->_usedNumaNodes.size());
|
||||
#if IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO
|
||||
auto concurrency = (0 == _impl->_config._threadsPerStream) ? custom::task_arena::automatic : _impl->_config._threadsPerStream;
|
||||
const auto concurrency = (0 == _impl->_config._threadsPerStream) ? custom::task_arena::automatic : _impl->_config._threadsPerStream;
|
||||
if (ThreadBindingType::HYBRID_AWARE == _impl->_config._threadBindingType) {
|
||||
_taskArena.reset(new custom::task_arena{
|
||||
custom::task_arena::constraints{}
|
||||
.set_core_type(custom::info::core_types().back())
|
||||
.set_max_concurrency(concurrency)
|
||||
});
|
||||
if (Config::PreferredCoreType::ROUND_ROBIN != _impl->_config._threadPreferredCoreType) {
|
||||
if (Config::PreferredCoreType::ANY == _impl->_config._threadPreferredCoreType) {
|
||||
_taskArena.reset(new custom::task_arena{concurrency});
|
||||
} else {
|
||||
const auto selected_core_type = Config::PreferredCoreType::BIG == _impl->_config._threadPreferredCoreType
|
||||
? custom::info::core_types().back() // running on Big cores only
|
||||
: custom::info::core_types().front(); // running on Little cores only
|
||||
_taskArena.reset(new custom::task_arena{
|
||||
custom::task_arena::constraints{}.set_core_type(selected_core_type).set_max_concurrency(concurrency)});
|
||||
}
|
||||
} else {
|
||||
// assigning the stream to the core type in the round-robin fashion
|
||||
// wrapping around total_streams (i.e. how many streams all different core types can handle together)
|
||||
const auto total_streams = _impl->total_streams_on_core_types.back().second;
|
||||
const auto streamId_wrapped = _streamId % total_streams;
|
||||
const auto& selected_core_type = std::find_if(_impl->total_streams_on_core_types.cbegin(), _impl->total_streams_on_core_types.cend(),
|
||||
[streamId_wrapped](const decltype(_impl->total_streams_on_core_types)::value_type & p) { return p.second > streamId_wrapped; })->first;
|
||||
_taskArena.reset(new custom::task_arena{
|
||||
custom::task_arena::constraints{}.set_core_type(selected_core_type).set_max_concurrency(concurrency)});
|
||||
}
|
||||
} else if (ThreadBindingType::NUMA == _impl->_config._threadBindingType) {
|
||||
_taskArena.reset(new custom::task_arena{
|
||||
custom::task_arena::constraints{}
|
||||
.set_numa_id(_numaNodeId)
|
||||
.set_max_concurrency(concurrency)
|
||||
});
|
||||
_taskArena.reset(new custom::task_arena{custom::task_arena::constraints{_numaNodeId, concurrency}});
|
||||
} else if ((0 != _impl->_config._threadsPerStream) || (ThreadBindingType::CORES == _impl->_config._threadBindingType)) {
|
||||
_taskArena.reset(new custom::task_arena{concurrency});
|
||||
if (ThreadBindingType::CORES == _impl->_config._threadBindingType) {
|
||||
@@ -164,6 +175,25 @@ struct CPUStreamsExecutor::Impl {
|
||||
} else {
|
||||
_usedNumaNodes = numaNodes;
|
||||
}
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
|
||||
if (ThreadBindingType::HYBRID_AWARE == config._threadBindingType) {
|
||||
const auto core_types = custom::info::core_types();
|
||||
const int threadsPerStream = (0 == config._threadsPerStream) ? std::thread::hardware_concurrency() : config._threadsPerStream;
|
||||
int sum = 0;
|
||||
// reversed order, so BIG cores are first
|
||||
for (auto iter = core_types.rbegin(); iter < core_types.rend(); iter++) {
|
||||
const auto& type = *iter;
|
||||
// calculating the #streams per core type
|
||||
const int num_streams_for_core_type = std::max(1,
|
||||
custom::info::default_concurrency(
|
||||
custom::task_arena::constraints{}.set_core_type(type)) / threadsPerStream);
|
||||
sum += num_streams_for_core_type;
|
||||
// prefix sum, so the core type for a given stream id will be deduced just as a upper_bound
|
||||
// (notice that the map keeps the elements in the descending order, so the big cores are populated first)
|
||||
total_streams_on_core_types.push_back({type, sum});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (auto streamId = 0; streamId < _config._streams; ++streamId) {
|
||||
_threads.emplace_back([this, streamId] {
|
||||
openvino::itt::threadName(_config._name + "_" + std::to_string(streamId));
|
||||
@@ -232,6 +262,14 @@ struct CPUStreamsExecutor::Impl {
|
||||
bool _isStopped = false;
|
||||
std::vector<int> _usedNumaNodes;
|
||||
ThreadLocal<std::shared_ptr<Stream>> _streams;
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
|
||||
// stream id mapping to the core type
|
||||
// stored in the reversed order (so the big cores, with the highest core_type_id value, are populated first)
|
||||
// every entry is the core type and #streams that this AND ALL EARLIER entries can handle (prefix sum)
|
||||
// (so mapping is actually just an upper_bound: core type is deduced from the entry for which the id < #streams)
|
||||
using StreamIdToCoreTypes = std::vector<std::pair<custom::core_type_id, int>>;
|
||||
StreamIdToCoreTypes total_streams_on_core_types;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ IStreamsExecutor::Ptr ExecutorManagerImpl::getIdleCPUStreamsExecutor(const IStre
|
||||
executorConfig._threadBindingType == config._threadBindingType &&
|
||||
executorConfig._threadBindingStep == config._threadBindingStep &&
|
||||
executorConfig._threadBindingOffset == config._threadBindingOffset)
|
||||
if (executorConfig._threadBindingType != IStreamsExecutor::ThreadBindingType::HYBRID_AWARE
|
||||
|| executorConfig._threadPreferredCoreType == config._threadPreferredCoreType)
|
||||
return executor;
|
||||
}
|
||||
auto newExec = std::make_shared<CPUStreamsExecutor>(config);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "ie_plugin_config.hpp"
|
||||
#include "cpp_interfaces/interface/ie_internal_plugin_config.hpp"
|
||||
#include "ie_parallel.hpp"
|
||||
#include "ie_parallel_custom_arena.hpp"
|
||||
#include "ie_system_conf.h"
|
||||
#include "ie_parameter.hpp"
|
||||
#include <string>
|
||||
@@ -29,32 +30,27 @@ std::vector<std::string> IStreamsExecutor::Config::SupportedKeys() {
|
||||
void IStreamsExecutor::Config::SetConfig(const std::string& key, const std::string& value) {
|
||||
if (key == CONFIG_KEY(CPU_BIND_THREAD)) {
|
||||
if (value == CONFIG_VALUE(YES) || value == CONFIG_VALUE(NUMA)) {
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO) && (TBB_INTERFACE_VERSION < 11100)
|
||||
if (value == CONFIG_VALUE(NUMA))
|
||||
IE_THROW() << CONFIG_KEY(CPU_BIND_THREAD) << " property value was set to NUMA. But IE was built with "
|
||||
<< "TBB version without NUMA-aware API. Current TBB API version is " << TBB_INTERFACE_VERSION
|
||||
<< ", required API version 11100 or greater.";
|
||||
#endif
|
||||
|
||||
#if (defined(__APPLE__) || defined(_WIN32))
|
||||
// on the Windows and Apple the CORES and NUMA pinning options are the same
|
||||
#if (defined(__APPLE__) || defined(_WIN32))
|
||||
_threadBindingType = IStreamsExecutor::ThreadBindingType::NUMA;
|
||||
#else
|
||||
#else
|
||||
_threadBindingType = (value == CONFIG_VALUE(YES))
|
||||
? IStreamsExecutor::ThreadBindingType::CORES : IStreamsExecutor::ThreadBindingType::NUMA;
|
||||
#endif
|
||||
#endif
|
||||
} else if (value == CONFIG_VALUE(HYBRID_AWARE)) {
|
||||
_threadBindingType = IStreamsExecutor::ThreadBindingType::HYBRID_AWARE;
|
||||
} else if (value == CONFIG_VALUE(NO)) {
|
||||
_threadBindingType = IStreamsExecutor::ThreadBindingType::NONE;
|
||||
} else {
|
||||
IE_THROW() << "Wrong value for property key " << CONFIG_KEY(CPU_BIND_THREAD)
|
||||
<< ". Expected only YES(binds to cores) / NO(no binding) / NUMA(binds to NUMA nodes)";
|
||||
<< ". Expected only YES(binds to cores) / NO(no binding) / NUMA(binds to NUMA nodes) / "
|
||||
"HYBRID_AWARE (let the runtime recognize and use the hybrid cores)";
|
||||
}
|
||||
} else if (key == CONFIG_KEY(CPU_THROUGHPUT_STREAMS)) {
|
||||
if (value == CONFIG_VALUE(CPU_THROUGHPUT_NUMA)) {
|
||||
_streams = static_cast<int>(getAvailableNUMANodes().size());
|
||||
} else if (value == CONFIG_VALUE(CPU_THROUGHPUT_AUTO)) {
|
||||
const int sockets = static_cast<int>(getAvailableNUMANodes().size());
|
||||
// bare minimum of streams (that evenly divides available number of core)
|
||||
// bare minimum of streams (that evenly divides available number of cores)
|
||||
const int num_cores = sockets == 1 ? std::thread::hardware_concurrency() : getNumberOfCPUCores();
|
||||
if (0 == num_cores % 4)
|
||||
_streams = std::max(4, num_cores / 4);
|
||||
@@ -138,12 +134,52 @@ Parameter IStreamsExecutor::Config::GetConfig(const std::string& key) {
|
||||
return {};
|
||||
}
|
||||
|
||||
IStreamsExecutor::Config IStreamsExecutor::Config::MakeDefaultMultiThreaded(const IStreamsExecutor::Config& initial) {
|
||||
IStreamsExecutor::Config IStreamsExecutor::Config::MakeDefaultMultiThreaded(const IStreamsExecutor::Config& initial, const bool fp_intesive) {
|
||||
const auto envThreads = parallel_get_env_threads();
|
||||
const auto& numaNodes = getAvailableNUMANodes();
|
||||
const auto numaNodesNum = numaNodes.size();
|
||||
const int numaNodesNum = numaNodes.size();
|
||||
auto streamExecutorConfig = initial;
|
||||
const auto hwCores = streamExecutorConfig._streams > 1 && numaNodesNum == 1 ? parallel_get_max_threads() : getNumberOfCPUCores();
|
||||
const bool bLatencyCase = streamExecutorConfig._streams <= numaNodesNum;
|
||||
|
||||
// by default, do not use the hyper-threading (to minimize threads synch overheads)
|
||||
int num_cores_default = getNumberOfCPUCores();
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
|
||||
//additional latency-case logic for hybrid processors:
|
||||
if (ThreadBindingType::HYBRID_AWARE == streamExecutorConfig._threadBindingType) {
|
||||
const auto core_types = custom::info::core_types();
|
||||
const auto num_little_cores = custom::info::default_concurrency(custom::task_arena::constraints{}.set_core_type(core_types.front()));
|
||||
const auto num_big_cores_phys = getNumberOfCPUCores(true);
|
||||
const int int8_threshold = 4; // ~relative efficiency of the VNNI-intensive code for Big vs Little cores;
|
||||
const int fp32_threshold = 2; // ~relative efficiency of the AVX2 fp32 code for Big vs Little cores;
|
||||
// by default the latency case uses (faster) Big cores only, depending on the compute ratio
|
||||
const bool bLatencyCaseBigOnly = num_big_cores_phys > (num_little_cores / (fp_intesive ? fp32_threshold : int8_threshold));
|
||||
// selecting the preferred core type
|
||||
streamExecutorConfig._threadPreferredCoreType =
|
||||
bLatencyCase
|
||||
? (bLatencyCaseBigOnly
|
||||
? IStreamsExecutor::Config::PreferredCoreType::BIG
|
||||
: IStreamsExecutor::Config::PreferredCoreType::ANY)
|
||||
: IStreamsExecutor::Config::PreferredCoreType::ROUND_ROBIN;
|
||||
// additionally selecting the #cores to use in the "Big-only" case
|
||||
if (bLatencyCaseBigOnly) {
|
||||
const int hyper_threading_threshold = 2; // min #cores, for which the hyper-threading becomes useful for the latency case
|
||||
const auto num_big_cores = custom::info::default_concurrency(custom::task_arena::constraints{}.set_core_type(core_types.back()));
|
||||
num_cores_default = (num_big_cores_phys <= hyper_threading_threshold) ? num_big_cores : num_big_cores_phys;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
const auto hwCores = !bLatencyCase && numaNodesNum == 1
|
||||
// throughput case on a single-NUMA node machine uses all available cores
|
||||
? parallel_get_max_threads()
|
||||
// in the rest of cases:
|
||||
// multi-node machine
|
||||
// or
|
||||
// latency case, single-node yet hybrid case that uses
|
||||
// all core types
|
||||
// or
|
||||
// big-cores only, but the #cores is "enough" (pls see the logic above)
|
||||
// it is usually beneficial not to use the hyper-threading (which is default)
|
||||
: num_cores_default;
|
||||
const auto threads = streamExecutorConfig._threads ? streamExecutorConfig._threads : (envThreads ? envThreads : hwCores);
|
||||
streamExecutorConfig._threadsPerStream = streamExecutorConfig._streams
|
||||
? std::max(1, threads/streamExecutorConfig._streams)
|
||||
|
||||
@@ -22,8 +22,6 @@ namespace custom {
|
||||
namespace detail {
|
||||
|
||||
#if USE_TBBBIND_2_4
|
||||
class binding_handler;
|
||||
|
||||
extern "C" {
|
||||
void __TBB_internal_initialize_system_topology(
|
||||
std::size_t groups_num,
|
||||
@@ -98,40 +96,34 @@ void initialize_system_topology() {
|
||||
});
|
||||
}
|
||||
|
||||
class binding_observer : public tbb::task_scheduler_observer {
|
||||
binding_handler* my_binding_handler;
|
||||
public:
|
||||
binding_observer(tbb::task_arena& ta, int num_slots, const constraints& c)
|
||||
: task_scheduler_observer(ta) {
|
||||
detail::initialize_system_topology();
|
||||
my_binding_handler = detail::__TBB_internal_allocate_binding_handler(num_slots, c.numa_id, c.core_type, c.max_threads_per_core);
|
||||
}
|
||||
~binding_observer() {
|
||||
detail::__TBB_internal_deallocate_binding_handler(my_binding_handler);
|
||||
}
|
||||
binding_observer::binding_observer(tbb::task_arena& ta, int num_slots, const constraints& c)
|
||||
: task_scheduler_observer(ta) {
|
||||
detail::initialize_system_topology();
|
||||
my_binding_handler = detail::__TBB_internal_allocate_binding_handler(num_slots, c.numa_id, c.core_type, c.max_threads_per_core);
|
||||
}
|
||||
|
||||
void on_scheduler_entry(bool) override {
|
||||
detail::__TBB_internal_apply_affinity(my_binding_handler, tbb::this_task_arena::current_thread_index());
|
||||
}
|
||||
void on_scheduler_exit(bool) override {
|
||||
detail::__TBB_internal_restore_affinity(my_binding_handler, tbb::this_task_arena::current_thread_index());
|
||||
}
|
||||
};
|
||||
binding_observer::~binding_observer() {
|
||||
detail::__TBB_internal_deallocate_binding_handler(my_binding_handler);
|
||||
}
|
||||
|
||||
binding_observer* construct_binding_observer(tbb::task_arena& ta, int num_slots, const constraints& c) {
|
||||
binding_observer* observer = nullptr;
|
||||
void binding_observer::on_scheduler_entry(bool) {
|
||||
detail::__TBB_internal_apply_affinity(my_binding_handler, tbb::this_task_arena::current_thread_index());
|
||||
}
|
||||
|
||||
void binding_observer::on_scheduler_exit(bool) {
|
||||
detail::__TBB_internal_restore_affinity(my_binding_handler, tbb::this_task_arena::current_thread_index());
|
||||
}
|
||||
|
||||
binding_oberver_ptr construct_binding_observer(tbb::task_arena& ta, int num_slots, const constraints& c) {
|
||||
binding_oberver_ptr observer{};
|
||||
if (detail::is_binding_environment_valid() &&
|
||||
((c.core_type >= 0 && info::core_types().size() > 1) || (c.numa_id >= 0 && info::numa_nodes().size() > 1) || c.max_threads_per_core > 0)) {
|
||||
observer = new binding_observer(ta, num_slots, c);
|
||||
observer.reset(new binding_observer{ta, num_slots, c});
|
||||
observer->observe(true);
|
||||
}
|
||||
return observer;
|
||||
}
|
||||
|
||||
void destroy_binding_observer(binding_observer* observer) {
|
||||
observer->observe(false);
|
||||
delete observer;
|
||||
}
|
||||
#endif /*USE_TBBBIND_2_4*/
|
||||
|
||||
#if TBB_NUMA_SUPPORT_PRESENT
|
||||
@@ -149,52 +141,52 @@ tbb::task_arena::constraints convert_constraints(custom::task_arena::constraints
|
||||
} // namespace detail
|
||||
|
||||
task_arena::task_arena(int max_concurrency_, unsigned reserved_for_masters)
|
||||
: tbb::task_arena{max_concurrency_, reserved_for_masters}
|
||||
: my_task_arena{max_concurrency_, reserved_for_masters}
|
||||
, my_initialization_state{}
|
||||
, my_constraints{}
|
||||
, my_binding_observer{nullptr}
|
||||
, my_binding_observer{}
|
||||
{}
|
||||
|
||||
task_arena::task_arena(const constraints& constraints_, unsigned reserved_for_masters)
|
||||
: tbb::task_arena{info::default_concurrency(constraints_), reserved_for_masters}
|
||||
: my_task_arena{info::default_concurrency(constraints_), reserved_for_masters}
|
||||
, my_initialization_state{}
|
||||
, my_constraints{constraints_}
|
||||
, my_binding_observer{nullptr}
|
||||
, my_binding_observer{}
|
||||
{}
|
||||
|
||||
task_arena::task_arena(const task_arena &s)
|
||||
: tbb::task_arena{s}
|
||||
: my_task_arena{s.my_task_arena}
|
||||
, my_initialization_state{}
|
||||
, my_constraints{s.my_constraints}
|
||||
, my_binding_observer{nullptr}
|
||||
, my_binding_observer{}
|
||||
{}
|
||||
|
||||
void task_arena::initialize() {
|
||||
#if USE_TBBBIND_2_4
|
||||
std::call_once(my_initialization_state, [this] {
|
||||
tbb::task_arena::initialize();
|
||||
my_task_arena.initialize();
|
||||
my_binding_observer = detail::construct_binding_observer(
|
||||
*this, tbb::task_arena::max_concurrency(), my_constraints);
|
||||
my_task_arena, my_task_arena.max_concurrency(), my_constraints);
|
||||
});
|
||||
#elif TBB_NUMA_SUPPORT_PRESENT || TBB_HYBRID_CPUS_SUPPORT_PRESENT
|
||||
tbb::task_arena::initialize(convert_constraints(my_constraints));
|
||||
my_task_arena.initialize(convert_constraints(my_constraints));
|
||||
#else
|
||||
tbb::task_arena::initialize();
|
||||
my_task_arena.initialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
void task_arena::initialize(int max_concurrency_, unsigned reserved_for_masters) {
|
||||
#if USE_TBBBIND_2_4
|
||||
std::call_once(my_initialization_state, [this, &max_concurrency_, &reserved_for_masters] {
|
||||
tbb::task_arena::initialize(max_concurrency_, reserved_for_masters);
|
||||
my_task_arena.initialize(max_concurrency_, reserved_for_masters);
|
||||
my_binding_observer = detail::construct_binding_observer(
|
||||
*this, tbb::task_arena::max_concurrency(), my_constraints);
|
||||
my_task_arena, my_task_arena.max_concurrency(), my_constraints);
|
||||
});
|
||||
#elif TBB_NUMA_SUPPORT_PRESENT || TBB_HYBRID_CPUS_SUPPORT_PRESENT
|
||||
my_constraints.max_concurrency = max_concurrency_;
|
||||
tbb::task_arena::initialize(convert_constraints(my_constraints), reserved_for_masters);
|
||||
my_task_arena.initialize(convert_constraints(my_constraints), reserved_for_masters);
|
||||
#else
|
||||
tbb::task_arena::initialize(max_concurrency_, reserved_for_masters);
|
||||
my_task_arena.initialize(max_concurrency_, reserved_for_masters);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -202,28 +194,24 @@ void task_arena::initialize(constraints constraints_, unsigned reserved_for_mast
|
||||
std::call_once(my_initialization_state, [this, &constraints_, &reserved_for_masters] {
|
||||
my_constraints = constraints_;
|
||||
#if USE_TBBBIND_2_4
|
||||
tbb::task_arena::initialize(info::default_concurrency(constraints_), reserved_for_masters);
|
||||
my_task_arena.initialize(info::default_concurrency(constraints_), reserved_for_masters);
|
||||
my_binding_observer = detail::construct_binding_observer(
|
||||
*this, tbb::task_arena::max_concurrency(), my_constraints);
|
||||
my_task_arena, my_task_arena.max_concurrency(), my_constraints);
|
||||
#elif TBB_NUMA_SUPPORT_PRESENT || TBB_HYBRID_CPUS_SUPPORT_PRESENT
|
||||
tbb::task_arena::initialize(convert_constraints(my_constraints), reserved_for_masters);
|
||||
my_task_arena.initialize(convert_constraints(my_constraints), reserved_for_masters);
|
||||
#else
|
||||
tbb::task_arena::initialize(my_constraints.max_concurrency, reserved_for_masters);
|
||||
my_task_arena.initialize(my_constraints.max_concurrency, reserved_for_masters);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
int task_arena::max_concurrency() {
|
||||
initialize();
|
||||
return tbb::task_arena::max_concurrency();
|
||||
task_arena::operator tbb::task_arena&() {
|
||||
return my_task_arena;
|
||||
}
|
||||
|
||||
task_arena::~task_arena() {
|
||||
#if USE_TBBBIND_2_4
|
||||
if (my_binding_observer != nullptr) {
|
||||
detail::destroy_binding_observer(my_binding_observer);
|
||||
}
|
||||
#endif
|
||||
int task_arena::max_concurrency() {
|
||||
initialize();
|
||||
return my_task_arena.max_concurrency();
|
||||
}
|
||||
|
||||
namespace info {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <type_traits>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace custom {
|
||||
|
||||
@@ -26,7 +27,7 @@ using core_type_id = int;
|
||||
|
||||
namespace detail {
|
||||
struct constraints {
|
||||
constraints(numa_node_id id = -1, int maximal_concurrency = -1)
|
||||
constraints(numa_node_id id = tbb::task_arena::automatic, int maximal_concurrency = tbb::task_arena::automatic)
|
||||
: numa_id{id}
|
||||
, max_concurrency{maximal_concurrency}
|
||||
, core_type{tbb::task_arena::automatic}
|
||||
@@ -56,13 +57,34 @@ struct constraints {
|
||||
int max_threads_per_core = tbb::task_arena::automatic;
|
||||
};
|
||||
|
||||
class binding_observer;
|
||||
class binding_handler;
|
||||
|
||||
class binding_observer : public tbb::task_scheduler_observer {
|
||||
binding_handler* my_binding_handler;
|
||||
public:
|
||||
binding_observer(tbb::task_arena& ta, int num_slots, const constraints& c);
|
||||
~binding_observer();
|
||||
|
||||
void on_scheduler_entry(bool) override;
|
||||
void on_scheduler_exit(bool) override;
|
||||
};
|
||||
|
||||
struct binding_observer_deleter {
|
||||
void operator()(binding_observer* observer) const {
|
||||
observer->observe(false);
|
||||
delete observer;
|
||||
}
|
||||
};
|
||||
|
||||
using binding_oberver_ptr = std::unique_ptr<binding_observer, binding_observer_deleter>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class task_arena : public tbb::task_arena {
|
||||
class task_arena {
|
||||
tbb::task_arena my_task_arena;
|
||||
std::once_flag my_initialization_state;
|
||||
detail::constraints my_constraints;
|
||||
detail::binding_observer* my_binding_observer;
|
||||
detail::binding_oberver_ptr my_binding_observer;
|
||||
|
||||
public:
|
||||
using constraints = detail::constraints;
|
||||
@@ -76,20 +98,20 @@ public:
|
||||
void initialize(int max_concurrency_, unsigned reserved_for_masters = 1);
|
||||
void initialize(constraints constraints_, unsigned reserved_for_masters = 1);
|
||||
|
||||
explicit operator tbb::task_arena&();
|
||||
|
||||
int max_concurrency();
|
||||
|
||||
template<typename F>
|
||||
void enqueue(F&& f) {
|
||||
initialize();
|
||||
tbb::task_arena::enqueue(std::forward<F>(f));
|
||||
my_task_arena.enqueue(std::forward<F>(f));
|
||||
}
|
||||
template<typename F>
|
||||
auto execute(F&& f) -> decltype(f()) {
|
||||
initialize();
|
||||
return tbb::task_arena::execute(std::forward<F>(f));
|
||||
return my_task_arena.execute(std::forward<F>(f));
|
||||
}
|
||||
|
||||
~task_arena();
|
||||
};
|
||||
|
||||
namespace info {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "ie_parallel.hpp"
|
||||
#include "ie_system_conf.h"
|
||||
|
||||
#include <cpp_interfaces/exception2status.hpp>
|
||||
#include <cpp_interfaces/interface/ie_internal_plugin_config.hpp>
|
||||
|
||||
namespace MKLDNNPlugin {
|
||||
@@ -21,16 +20,20 @@ namespace MKLDNNPlugin {
|
||||
using namespace InferenceEngine;
|
||||
|
||||
Config::Config() {
|
||||
#if (defined(__APPLE__) || defined(_WIN32))
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO) && (TBB_INTERFACE_VERSION >= 11100)
|
||||
// If we sure that TBB has NUMA aware API part.
|
||||
streamExecutorConfig._threadBindingType = InferenceEngine::IStreamsExecutor::NUMA;
|
||||
#else
|
||||
streamExecutorConfig._threadBindingType = InferenceEngine::IStreamsExecutor::NONE;
|
||||
#endif
|
||||
#else
|
||||
// this is default mode
|
||||
streamExecutorConfig._threadBindingType = InferenceEngine::IStreamsExecutor::CORES;
|
||||
#endif
|
||||
|
||||
// for the TBB code-path, additional configuration depending on the OS and CPU types
|
||||
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
// 'CORES' is not implemented for Win/MacOS; so the 'NUMA' is default
|
||||
streamExecutorConfig._threadBindingType = InferenceEngine::IStreamsExecutor::NUMA;
|
||||
#endif
|
||||
|
||||
if (getAvailableCoresTypes().size() > 1 /*Hybrid CPU*/) {
|
||||
streamExecutorConfig._threadBindingType = InferenceEngine::IStreamsExecutor::HYBRID_AWARE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!with_cpu_x86_bfloat16())
|
||||
enforceBF16 = false;
|
||||
@@ -128,7 +131,7 @@ void Config::updateProperties() {
|
||||
_config.insert({ PluginConfigParams::KEY_CPU_BIND_THREAD, PluginConfigParams::NUMA });
|
||||
break;
|
||||
case IStreamsExecutor::ThreadBindingType::HYBRID_AWARE:
|
||||
_config.insert({ PluginConfigParams::KEY_CPU_BIND_THREAD, PluginConfigParams::HYBRID_AWARE});
|
||||
_config.insert({ PluginConfigParams::KEY_CPU_BIND_THREAD, PluginConfigParams::HYBRID_AWARE });
|
||||
break;
|
||||
}
|
||||
if (collectPerfCounters == true)
|
||||
|
||||
@@ -49,11 +49,11 @@ MKLDNNExecNetwork::MKLDNNExecNetwork(const InferenceEngine::CNNNetwork &network,
|
||||
// we are cloning network if we have statistics and we can transform network.
|
||||
_clonedNetwork = cloneNetwork(network);
|
||||
|
||||
bool isFloatModel = true;
|
||||
if (_cfg.lpTransformsMode == Config::LPTransformsMode::On) {
|
||||
// Check if network is INT8 or Binary.
|
||||
// BF16 transformations were disabled since CPU plug-in doesn't support mixed precision execution:
|
||||
// BF16 + INT8 or BF16 + BIN.
|
||||
bool isFloatModel = true;
|
||||
CNNNetworkIterator iter(network);
|
||||
while (iter != CNNNetworkIterator()) {
|
||||
if (CaselessEq<std::string>()((*iter)->type, "FakeQuantize")) {
|
||||
@@ -229,7 +229,7 @@ MKLDNNExecNetwork::MKLDNNExecNetwork(const InferenceEngine::CNNNetwork &network,
|
||||
// special case when all InferRequests are muxed into a single queue
|
||||
_taskExecutor = InferenceEngine::ExecutorManager::getInstance()->getExecutor("CPU");
|
||||
} else {
|
||||
auto streamsExecutorConfig = InferenceEngine::IStreamsExecutor::Config::MakeDefaultMultiThreaded(_cfg.streamExecutorConfig);
|
||||
auto streamsExecutorConfig = InferenceEngine::IStreamsExecutor::Config::MakeDefaultMultiThreaded(_cfg.streamExecutorConfig, isFloatModel);
|
||||
streamsExecutorConfig._name = "CPUStreamsExecutor";
|
||||
_taskExecutor = InferenceEngine::ExecutorManager::getInstance()->getIdleCPUStreamsExecutor(streamsExecutorConfig);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,8 @@ NGRAPH_RTTI_DEFINITION(ngraph::pass::POTTransformations, "POTTransformations", 0
|
||||
|
||||
bool ngraph::pass::POTTransformations::run_on_function(std::shared_ptr<ngraph::Function> f) {
|
||||
ngraph::pass::Manager manager(get_pass_config());
|
||||
if (m_device == "CPU") {
|
||||
// TODO: register CPU passes
|
||||
// manager.register_pass<ngraph::pass::LSTMCellDecomposition>();
|
||||
} else {
|
||||
throw ngraph_error("Device name is unsupported");
|
||||
if (m_device == "GNA") {
|
||||
manager.register_pass<ngraph::pass::LSTMCellDecomposition>();
|
||||
}
|
||||
manager.run_passes(f);
|
||||
return false;
|
||||
|
||||
@@ -37,12 +37,23 @@ INFERENCE_ENGINE_API_CPP(bool) checkOpenMpEnvVars(bool includeOMPNumThreads = tr
|
||||
INFERENCE_ENGINE_API_CPP(std::vector<int>) getAvailableNUMANodes();
|
||||
|
||||
/**
|
||||
* @brief Returns number of CPU physical cores on Linux/Windows (which is considered to be more performance friendly for servers)
|
||||
* (on other OSes it simply relies on the original parallel API of choice, which usually uses the logical cores )
|
||||
* @brief Returns available CPU cores types (on Linux, and Windows) and ONLY with TBB, single core type is assumed otherwise
|
||||
* @ingroup ie_dev_api_system_conf
|
||||
* @return Vector of core types
|
||||
*/
|
||||
INFERENCE_ENGINE_API_CPP(std::vector<int>) getAvailableCoresTypes();
|
||||
|
||||
/**
|
||||
* @brief Returns number of CPU physical cores on Linux/Windows (which is considered to be more performance friendly for servers)
|
||||
* (on other OSes it simply relies on the original parallel API of choice, which usually uses the logical cores).
|
||||
* call function with 'false' to get #phys cores of all types
|
||||
* call function with 'true' to get #phys 'Big' cores
|
||||
* number of 'Little' = 'all' - 'Big'
|
||||
* @ingroup ie_dev_api_system_conf
|
||||
* @param[in] bigCoresOnly Additionally limits the number of reported cores to the 'Big' cores only.
|
||||
* @return Number of physical CPU cores.
|
||||
*/
|
||||
INFERENCE_ENGINE_API_CPP(int) getNumberOfCPUCores();
|
||||
INFERENCE_ENGINE_API_CPP(int) getNumberOfCPUCores(bool bigCoresOnly = false);
|
||||
|
||||
/**
|
||||
* @brief Checks whether CPU supports SSE 4.2 capability
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
using Ptr = std::shared_ptr<IStreamsExecutor>;
|
||||
|
||||
/**
|
||||
* @brief Defines thread binding type
|
||||
* @brief Defines inference thread binding type
|
||||
*/
|
||||
enum ThreadBindingType : std::uint8_t {
|
||||
NONE, //!< Don't bind the inference threads
|
||||
@@ -74,9 +74,11 @@ public:
|
||||
* @brief Create appropriate multithreaded configuration
|
||||
* filing unconfigured values from initial configuration using hardware properties
|
||||
* @param initial Inital configuration
|
||||
* @param fp_intesive additional hint for the the (Hybrid) core-types selection logic
|
||||
* whether the executor should be configured for floating point intensive work (as opposite to int8 intensive)
|
||||
* @return configured values
|
||||
*/
|
||||
static Config MakeDefaultMultiThreaded(const Config& initial);
|
||||
static Config MakeDefaultMultiThreaded(const Config& initial, const bool fp_intesive = true);
|
||||
|
||||
std::string _name; //!< Used by `ITT` to name executor threads
|
||||
int _streams = 1; //!< Number of streams.
|
||||
@@ -85,6 +87,12 @@ public:
|
||||
int _threadBindingStep = 1; //!< In case of @ref CORES binding offset type thread binded to cores with defined step
|
||||
int _threadBindingOffset = 0; //!< In case of @ref CORES binding offset type thread binded to cores starting from offset
|
||||
int _threads = 0; //!< Number of threads distributed between streams. Reserved. Should not be used.
|
||||
enum PreferredCoreType {
|
||||
ANY,
|
||||
LITTLE,
|
||||
BIG,
|
||||
ROUND_ROBIN // used w/multiple streams to populate the Big cores first, then the Little, then wrap around (for large #streams)
|
||||
} _threadPreferredCoreType = PreferredCoreType::ANY; //!< In case of @ref HYBRID_AWARE hints the TBB to affinitize
|
||||
|
||||
/**
|
||||
* @brief A constructor with arguments
|
||||
@@ -96,6 +104,7 @@ public:
|
||||
* @param[in] threadBindingStep @copybrief Config::_threadBindingStep
|
||||
* @param[in] threadBindingOffset @copybrief Config::_threadBindingOffset
|
||||
* @param[in] threads @copybrief Config::_threads
|
||||
* @param[in] threadPreferBigCores @copybrief Config::_threadPreferBigCores
|
||||
*/
|
||||
Config(
|
||||
std::string name = "StreamsExecutor",
|
||||
@@ -104,14 +113,15 @@ public:
|
||||
ThreadBindingType threadBindingType = ThreadBindingType::NONE,
|
||||
int threadBindingStep = 1,
|
||||
int threadBindingOffset = 0,
|
||||
int threads = 0) :
|
||||
int threads = 0,
|
||||
PreferredCoreType threadPreferredCoreType = PreferredCoreType::ANY) :
|
||||
_name{name},
|
||||
_streams{streams},
|
||||
_threadsPerStream{threadsPerStream},
|
||||
_threadBindingType{threadBindingType},
|
||||
_threadBindingStep{threadBindingStep},
|
||||
_threadBindingOffset{threadBindingOffset},
|
||||
_threads{threads} {
|
||||
_threads{threads}, _threadPreferredCoreType(threadPreferredCoreType){
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace ngraph {
|
||||
namespace op {
|
||||
|
||||
/// A base class for templated TypeRelaxed that maintains overridden input types and output types for an operation.
|
||||
class TRANSFORMATIONS_API TypeRelaxedBase {
|
||||
class NGRAPH_API TypeRelaxedBase {
|
||||
public:
|
||||
virtual ~TypeRelaxedBase();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
namespace ngraph {
|
||||
namespace pass {
|
||||
|
||||
class TRANSFORMATIONS_API ConvertPrecision;
|
||||
class NGRAPH_API ConvertPrecision;
|
||||
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
|
||||
@@ -1,600 +0,0 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "itt.hpp"
|
||||
#include "transformations/convert_precision.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <ngraph/opsets/opset6.hpp>
|
||||
#include <ngraph/opsets/opset5.hpp>
|
||||
#include <ngraph/opsets/opset4.hpp>
|
||||
#include <ngraph/opsets/opset3.hpp>
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
#include <ngraph_ops/type_relaxed.hpp>
|
||||
|
||||
#include <ngraph/runtime/reference/convert.hpp>
|
||||
|
||||
using namespace ngraph;
|
||||
|
||||
bool fuse_type_to_constant(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, const std::vector<ngraph::Input<ngraph::Node>> & consumers);
|
||||
bool fuse_type_to_shapeof(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_shapeof_v0(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_parameter(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_convert(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_nms3(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_nms4(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_nms5(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_topk(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_nonzero(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_bucketize(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
bool fuse_type_to_ctc_greedy_decoder_seq_len(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
|
||||
bool extend_select_type(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx);
|
||||
|
||||
template <typename T>
|
||||
bool fuse_type_to_binary_comparision(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node)) {
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
return true;
|
||||
} else if (auto casted = std::dynamic_pointer_cast<T>(node)) {
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<T>>(*casted, element::TypeVector{}, element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool fuse_type_to_logical(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node)) {
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
type_relaxed->set_origin_input_type(element::boolean, 0);
|
||||
type_relaxed->set_origin_input_type(element::boolean, 1);
|
||||
return true;
|
||||
} else if (auto casted = std::dynamic_pointer_cast<T>(node)) {
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<T>>(*casted,
|
||||
element::TypeVector{element::boolean, element::boolean}, element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool fuse_type_to_reduce_logical(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node)) {
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
type_relaxed->set_origin_input_type(element::boolean, 0);
|
||||
return true;
|
||||
} else if (auto casted = std::dynamic_pointer_cast<T>(node)) {
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<T>>(*casted,
|
||||
element::TypeVector{element::boolean}, element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertPrecision, "ConvertPrecision", 0);
|
||||
|
||||
bool ngraph::pass::ConvertPrecision::run_on_function(std::shared_ptr<ngraph::Function> f) {
|
||||
RUN_ON_FUNCTION_SCOPE(ConvertPrecision);
|
||||
type_to_fuse_map type_to_fuse {
|
||||
{opset4::Parameter::type_info, fuse_type_to_parameter},
|
||||
{opset4::Convert::type_info, fuse_type_to_convert},
|
||||
{opset4::ShapeOf::type_info, fuse_type_to_shapeof},
|
||||
{opset3::NonMaxSuppression::type_info, fuse_type_to_nms3},
|
||||
{opset4::NonMaxSuppression::type_info, fuse_type_to_nms4},
|
||||
{opset5::NonMaxSuppression::type_info, fuse_type_to_nms5},
|
||||
{opset6::CTCGreedyDecoderSeqLen::type_info, fuse_type_to_ctc_greedy_decoder_seq_len},
|
||||
{opset4::TopK::type_info, fuse_type_to_topk},
|
||||
{opset4::NonZero::type_info, fuse_type_to_nonzero},
|
||||
{opset4::Bucketize::type_info, fuse_type_to_bucketize},
|
||||
{opset4::Equal::type_info, fuse_type_to_binary_comparision<opset4::Equal>},
|
||||
{opset4::NotEqual::type_info, fuse_type_to_binary_comparision<opset4::NotEqual>},
|
||||
{opset4::Greater::type_info, fuse_type_to_binary_comparision<opset4::Greater>},
|
||||
{opset4::GreaterEqual::type_info, fuse_type_to_binary_comparision<opset4::GreaterEqual>},
|
||||
{opset4::Less::type_info, fuse_type_to_binary_comparision<opset4::Less>},
|
||||
{opset4::LessEqual::type_info, fuse_type_to_binary_comparision<opset4::LessEqual>},
|
||||
{opset4::LogicalAnd::type_info, fuse_type_to_logical<opset4::LogicalAnd>},
|
||||
{opset4::LogicalOr::type_info, fuse_type_to_logical<opset4::LogicalOr>},
|
||||
{opset4::LogicalXor::type_info, fuse_type_to_logical<opset4::LogicalXor>},
|
||||
{opset4::LogicalNot::type_info, fuse_type_to_logical<opset4::LogicalNot>},
|
||||
{opset4::ReduceLogicalAnd::type_info, fuse_type_to_reduce_logical<opset4::ReduceLogicalAnd>},
|
||||
{opset4::ReduceLogicalOr::type_info, fuse_type_to_reduce_logical<opset4::ReduceLogicalOr>},
|
||||
{opset1::ShapeOf::type_info, fuse_type_to_shapeof_v0}
|
||||
};
|
||||
|
||||
type_to_fuse.insert(m_additional_type_to_fuse_map.begin(), m_additional_type_to_fuse_map.end());
|
||||
|
||||
static type_to_fuse_map type_to_extend {
|
||||
{opset4::Select::type_info, extend_select_type},
|
||||
};
|
||||
|
||||
// As Constant operations can be shared between multiple nGraph Functions so before
|
||||
// changing precision we need to understand which Constant consumers belongs
|
||||
// to the current nGraph Function
|
||||
std::map<const std::shared_ptr<ngraph::Node>, std::vector<Input<Node>>> const_to_internal_output;
|
||||
|
||||
std::function<void(const std::shared_ptr<Function> &)> register_constants =
|
||||
[&const_to_internal_output, ®ister_constants](const std::shared_ptr<Function> & f) {
|
||||
for (auto & node : f->get_ordered_ops()) {
|
||||
for (auto & input : node->inputs()) {
|
||||
if (auto const_node = std::dynamic_pointer_cast<opset4::Constant>(input.get_source_output().get_node_shared_ptr())) {
|
||||
const_to_internal_output[const_node].emplace_back(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto convert_node_output_precision = [this, &const_to_internal_output, &type_to_fuse](const std::shared_ptr<ngraph::Node> & node) {
|
||||
for (auto output : node->outputs()) {
|
||||
if (output.get_element_type() == m_from) {
|
||||
// Handle case with Constants as they can have consumers from other nGraph Function object
|
||||
if (ngraph::op::is_constant(node) && const_to_internal_output.count(node)) {
|
||||
fuse_type_to_constant(node, m_to, const_to_internal_output.at(node));
|
||||
break;
|
||||
}
|
||||
|
||||
// Check that node type exists in map and we can fuse type into node
|
||||
if (type_to_fuse.count(node->get_type_info()) &&
|
||||
type_to_fuse.at(node->get_type_info())(node, m_to, output.get_index())) {
|
||||
// We need to break if original node was replaced
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto convert_node_input_precision = [this](const std::shared_ptr<ngraph::Node> & node) {
|
||||
for (auto input : node->inputs()) {
|
||||
if (input.get_element_type() == m_from) {
|
||||
// For some operations we need to extend their input types to support new type
|
||||
if (type_to_extend.count(node->get_type_info()) &&
|
||||
type_to_extend.at(node->get_type_info())(node, m_to, input.get_index())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::function<void(const std::shared_ptr<Function> &)> convert_function_precision =
|
||||
[this, &const_to_internal_output,
|
||||
®ister_constants,
|
||||
&convert_node_output_precision,
|
||||
&convert_node_input_precision,
|
||||
&convert_function_precision] (const std::shared_ptr<Function> & f) {
|
||||
// Iterate over all nodes in topological order and then iterate over node outputs.
|
||||
// If output type mismatch given type we try to fuse type into this operation
|
||||
// otherwise we insert Convert operation.
|
||||
for (auto &node : f->get_ordered_ops()) {
|
||||
transformation_callback(node);
|
||||
// Recursively apply transformation for sub-graph based operations
|
||||
if (auto sub_graph_node = std::dynamic_pointer_cast<op::util::SubGraphOp>(node)) {
|
||||
if (auto sub_graph = sub_graph_node->get_function()) {
|
||||
convert_function_precision(sub_graph);
|
||||
}
|
||||
}
|
||||
convert_node_input_precision(node);
|
||||
}
|
||||
// Register internal constants only after fixing input type that could lead to nodes replacement
|
||||
register_constants(f);
|
||||
|
||||
for (auto &node : f->get_ordered_ops()) {
|
||||
convert_node_output_precision(node);
|
||||
}
|
||||
};
|
||||
|
||||
convert_function_precision(f);
|
||||
f->validate_nodes_and_infer_types();
|
||||
|
||||
// TODO: we need to split NopElimination pass to separate MatcherPasses and call Convert elimination here
|
||||
for (auto &node : f->get_ordered_ops()) {
|
||||
if (auto convert = std::dynamic_pointer_cast<opset4::Convert>(node)) {
|
||||
// WA for topK, dont remove fake convert
|
||||
if (convert->input(0).get_element_type() == convert->get_convert_element_type() &&
|
||||
convert->input_value(0).get_node_shared_ptr()->get_output_size() == 1) {
|
||||
replace_output_update_name(convert->output(0), convert->input_value(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fuse_type_to_shapeof(const std::shared_ptr<ngraph::Node> & node, element::Type to, size_t idx) {
|
||||
if (auto shapeof = as_type_ptr<opset4::ShapeOf>(node)) {
|
||||
if (to == element::i32 || to == element::i64) {
|
||||
shapeof->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_parameter(const std::shared_ptr<ngraph::Node> & node, element::Type to, size_t idx) {
|
||||
if (auto param = as_type_ptr<opset4::Parameter>(node)) {
|
||||
param->set_element_type(to);
|
||||
param->validate_and_infer_types();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_convert(const std::shared_ptr<ngraph::Node> & node, element::Type to, size_t idx) {
|
||||
if (auto convert = as_type_ptr<opset4::Convert>(node)) {
|
||||
convert->set_convert_element_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nms3(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto nms = as_type_ptr<opset3::NonMaxSuppression>(node)) {
|
||||
nms->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nms4(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto nms = as_type_ptr<opset4::NonMaxSuppression>(node)) {
|
||||
nms->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nms5(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto nms = as_type_ptr<opset5::NonMaxSuppression>(node)) {
|
||||
nms->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_topk(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto topk = as_type_ptr<opset4::TopK>(node)) {
|
||||
if (idx == 1 && (to == element::i32 || to == element::i64)) {
|
||||
topk->set_index_element_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_ctc_greedy_decoder_seq_len(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto ctc_decoder = as_type_ptr<opset6::CTCGreedyDecoderSeqLen>(node)) {
|
||||
if (idx == 0 && (to == element::i32 || to == element::i64)) {
|
||||
ctc_decoder->set_classes_index_type(to);
|
||||
return true;
|
||||
}
|
||||
if (idx == 1 && (to == element::i32 || to == element::i64)) {
|
||||
ctc_decoder->set_sequence_length_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nonzero(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto nonzero = as_type_ptr<opset4::NonZero>(node)) {
|
||||
if (to == element::i32 || to == element::i64) {
|
||||
nonzero->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_bucketize(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto b = as_type_ptr<opset4::Bucketize>(node)) {
|
||||
if (to == element::i32 || to == element::i64) {
|
||||
b->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_shapeof_v0(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node)) {
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
return true;
|
||||
} else if (auto casted = std::dynamic_pointer_cast<opset1::ShapeOf>(node)) {
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<opset1::ShapeOf>>(*casted,
|
||||
element::TypeVector{}, element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool extend_select_type(const std::shared_ptr<ngraph::Node> & node, ngraph::element::Type to, size_t idx) {
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node)) {
|
||||
type_relaxed->set_origin_input_type(element::boolean, 0);
|
||||
return true;
|
||||
} else if (auto casted = std::dynamic_pointer_cast<opset4::Select>(node)) {
|
||||
auto relaxed_op = std::make_shared<op::TypeRelaxed<opset4::Select>>(*casted,
|
||||
element::TypeVector{element::boolean},
|
||||
element::TypeVector{});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename src_type, typename dst_type>
|
||||
inline dst_type convert_value(src_type val) {
|
||||
if (val > std::numeric_limits<dst_type>::max()) {
|
||||
return std::numeric_limits<dst_type>::max();
|
||||
} else if (val < std::numeric_limits<dst_type>::lowest()) {
|
||||
return std::numeric_limits<dst_type>::lowest();
|
||||
}
|
||||
return static_cast<dst_type>(val);
|
||||
}
|
||||
|
||||
// We need to treat U64->I32 and U32->I32 as a separate case, because of C++'s implicit promotion from signed to unsigned,
|
||||
// and we don't need to compare and clamp the input to std::numeric_limits<int32_t>::lowest()
|
||||
template <>
|
||||
inline int32_t convert_value<uint64_t, int32_t>(uint64_t val) {
|
||||
if (val > static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
|
||||
return std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
return static_cast<int32_t>(val);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int32_t convert_value<uint32_t, int32_t>(uint32_t val) {
|
||||
if (val > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
|
||||
return std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
return static_cast<int32_t>(val);
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <element::Type_t PREC_FROM, element::Type_t PREC_TO>
|
||||
std::shared_ptr<ngraph::Node> change_constant_precision(std::shared_ptr<opset4::Constant>& constant) {
|
||||
using src_type = typename element_type_traits<PREC_FROM>::value_type;
|
||||
using dst_type = typename element_type_traits<PREC_TO>::value_type;
|
||||
|
||||
const auto * src_data = constant->get_data_ptr<src_type>();
|
||||
const auto size = shape_size(constant->get_shape());
|
||||
|
||||
auto new_constant = std::make_shared<ngraph::opset4::Constant>(PREC_TO, constant->get_shape());
|
||||
auto * dst_data = const_cast<dst_type *>(reinterpret_cast<const dst_type *>(new_constant->get_data_ptr()));
|
||||
if (dst_data == nullptr)
|
||||
throw ngraph_error("Can't get destination data pointer");
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
dst_data[i] = convert_value<src_type, dst_type>(src_data[i]);
|
||||
}
|
||||
return new_constant;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::shared_ptr<Node> change_constant_precision<element::Type_t::f16, element::Type_t::f32>(std::shared_ptr<opset4::Constant>& constant) {
|
||||
using src_type = typename element_type_traits<element::Type_t::f16>::value_type;
|
||||
using dst_type = typename element_type_traits<element::Type_t::f32>::value_type;
|
||||
|
||||
const auto * src_data = constant->get_data_ptr<src_type>();
|
||||
const auto size = shape_size(constant->get_shape());
|
||||
|
||||
auto new_constant = std::make_shared<ngraph::opset4::Constant>(element::Type_t::f32, constant->get_shape());
|
||||
auto * dst_data = const_cast<dst_type *>(reinterpret_cast<const dst_type *>(new_constant->get_data_ptr()));
|
||||
if (dst_data == nullptr)
|
||||
throw ngraph_error("Can't get destination data pointer");
|
||||
|
||||
ngraph::runtime::reference::convert<src_type, dst_type>(src_data, dst_data, size);
|
||||
|
||||
return new_constant;
|
||||
}
|
||||
|
||||
struct EnumClassHash {
|
||||
template<class T>
|
||||
std::size_t operator()(T t) const {
|
||||
return static_cast<size_t>(t);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Method converts low precision integer types
|
||||
* The method uses the next logic for conversion:
|
||||
* * For unsigned types we just copy all bits to destination type (which is bigger):
|
||||
* int4 [1011] -> int8 [00001011]
|
||||
* * For signed types we copy all bits (except sign bit) to destination type and after
|
||||
* that for negative values we set to 1 all higher bits:
|
||||
* int4 [1011] -> int8 [11111011]
|
||||
*
|
||||
* @param src source value !!! the type must be unsigned !!!
|
||||
* @param dst destination value !!! the type must be unsigned !!!
|
||||
* @param src_offset source offset (for custom data types)
|
||||
* @param src_size source size (for custom data types)
|
||||
* @param dst_offset destination offset
|
||||
* @param dst_size destination size
|
||||
* @param is_signed the type of source data
|
||||
*/
|
||||
template <class SRC, class DST>
|
||||
void convert_lp_value(const SRC& src, DST& dst, size_t src_offset, size_t src_size, size_t dst_offset, size_t dst_size, bool is_signed) {
|
||||
constexpr SRC src_max = std::numeric_limits<SRC>::max();
|
||||
constexpr DST dst_max = std::numeric_limits<DST>::max();
|
||||
// Make a shift for the source value
|
||||
// src [11101000] offset 2, size 4
|
||||
// val [00011101]
|
||||
SRC val = src >> src_offset;
|
||||
// dst [10001111 00000100] offset 5 size 9
|
||||
// new_val [00000000 00000000]
|
||||
DST new_val = 0;
|
||||
|
||||
// Calculate diff in order to clean bits which don't exist in the source value
|
||||
// diff 4
|
||||
size_t diff = sizeof(SRC)*8 - src_size;
|
||||
// Clean unnecessary bits
|
||||
// val [11010000]
|
||||
val = val << diff;
|
||||
// val [00001101]
|
||||
val = val >> diff;
|
||||
|
||||
// Get the sign of value
|
||||
// sign [00000001]
|
||||
SRC sign = (val >> (src_size - 1)) & 0b1;
|
||||
|
||||
// If source type is signed and negative
|
||||
if (is_signed && sign) {
|
||||
// val [11111101]
|
||||
val |= src_max << diff;
|
||||
// new_val [00000001 11111111]
|
||||
new_val = dst_max >> (sizeof(DST) * 8 - dst_size);
|
||||
// new_val [00000001 11111101]
|
||||
new_val &= (dst_max << sizeof(SRC)*8) | val;
|
||||
} else {
|
||||
// new_val [00000000 00001101]
|
||||
new_val = val;
|
||||
}
|
||||
|
||||
// Make a mask in order to save other values if DST contains several values
|
||||
// mask [11000000 00011111]
|
||||
DST mask = 0;
|
||||
if (dst_offset + dst_size < sizeof(DST) * 8)
|
||||
mask = (dst_max << (dst_offset + dst_size));
|
||||
if (dst_offset != 0)
|
||||
mask |= (dst_max >> (sizeof(DST) * 8 - dst_offset));
|
||||
|
||||
// Add mask to our converted value
|
||||
// signed: new_val [11100000 10111111]
|
||||
// unsigned: new_val [11000001 10111111]
|
||||
new_val = mask | (new_val << dst_offset);
|
||||
|
||||
// Add our value to destination
|
||||
// dst: [10111111 11100100]
|
||||
dst |= ~mask;
|
||||
// signed: dst [10100000 10100100]
|
||||
// unsigned: dst [10000001 10100100]
|
||||
dst &= new_val;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> convert_low_precisions_int(std::shared_ptr<opset4::Constant>& constant, element::Type to) {
|
||||
// Supported integer precisions
|
||||
static const std::unordered_set<element::Type_t, EnumClassHash> supported_integer_precisions = {
|
||||
element::i4,
|
||||
element::u4,
|
||||
element::u1
|
||||
};
|
||||
// Get source element type and source data
|
||||
auto src_type = constant->get_element_type();
|
||||
const auto* src_data = reinterpret_cast<const uint8_t*>(constant->get_data_ptr());
|
||||
|
||||
// We support conversion only if several elements can be represented in one instance of some C++ common data type without any exception,
|
||||
// destination data type should be bigger than source and destination data type should be real
|
||||
if (!supported_integer_precisions.count(src_type) || (src_type.size() * 8) % src_type.bitwidth() ||
|
||||
(to.size() * 8) % to.bitwidth() || to.is_real() || to.bitwidth() < src_type.bitwidth())
|
||||
throw ngraph_error("Convert low precision for " + constant->get_element_type().get_type_name() + " to " +
|
||||
to.get_type_name() + " is not implemented!");
|
||||
|
||||
// Create a new constant operation and get destination data
|
||||
auto new_constant = std::make_shared<ngraph::opset4::Constant>(to, constant->get_shape());
|
||||
auto* dst_data = const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(new_constant->get_data_ptr()));
|
||||
// Check pointers
|
||||
if (src_data == nullptr || dst_data == nullptr)
|
||||
throw ngraph_error("Can't get data pointer");
|
||||
|
||||
// Convert values
|
||||
const auto size = shape_size(constant->get_shape());
|
||||
size_t src_idx(0), dst_idx(0), dst_off(0), src_off(0);
|
||||
if (src_type.bitwidth() < 8) {
|
||||
src_off = 8 - src_type.bitwidth();
|
||||
}
|
||||
|
||||
if (to.bitwidth() < 8) {
|
||||
dst_off = 8 - to.bitwidth();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Source type at the current moment always less than 1 byte
|
||||
// Select the right destination type
|
||||
switch (to.size()) {
|
||||
case 1:
|
||||
convert_lp_value<uint8_t, uint8_t>(src_data[src_idx], dst_data[dst_idx], src_off, src_type.bitwidth(),
|
||||
dst_off, to.bitwidth(), src_type.is_signed());
|
||||
break;
|
||||
case 2:
|
||||
convert_lp_value<uint8_t, uint16_t>(src_data[src_idx], reinterpret_cast<uint16_t*>(dst_data)[dst_idx], src_off, src_type.bitwidth(),
|
||||
dst_off, to.bitwidth(), src_type.is_signed());
|
||||
break;
|
||||
case 4:
|
||||
convert_lp_value<uint8_t, uint32_t>(src_data[src_idx], reinterpret_cast<uint32_t*>(dst_data)[dst_idx], src_off, src_type.bitwidth(),
|
||||
dst_off, to.bitwidth(), src_type.is_signed());
|
||||
break;
|
||||
case 8:
|
||||
convert_lp_value<uint8_t, uint64_t>(src_data[src_idx], reinterpret_cast<uint64_t*>(dst_data)[dst_idx], src_off, src_type.bitwidth(),
|
||||
dst_off, to.bitwidth(), src_type.is_signed());
|
||||
break;
|
||||
default:
|
||||
throw ngraph_error("Unsupported element size!");
|
||||
}
|
||||
// Calculate offsets and indexes
|
||||
if (src_type.bitwidth() < 8) {
|
||||
if (src_off == 0) {
|
||||
src_off = 8;
|
||||
src_idx++;
|
||||
}
|
||||
src_off -= src_type.bitwidth();
|
||||
} else {
|
||||
src_idx++;
|
||||
}
|
||||
if (to.bitwidth() < 8) {
|
||||
if (dst_off == 0) {
|
||||
dst_off = 8;
|
||||
dst_idx++;
|
||||
}
|
||||
dst_off -= to.bitwidth();
|
||||
} else {
|
||||
dst_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
return new_constant;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool fuse_type_to_constant(const std::shared_ptr<ngraph::Node> & node, element::Type to, const std::vector<Input<Node>> & consumers) {
|
||||
if (auto constant = as_type_ptr<opset4::Constant>(node)) {
|
||||
auto from = constant->get_element_type();
|
||||
std::shared_ptr<ngraph::Node> new_const;
|
||||
if (from == element::u64 && to == element::i32) {
|
||||
new_const = change_constant_precision<element::Type_t::u64, element::Type_t::i32>(constant);
|
||||
} else if (from == element::i64 && to == element::i32) {
|
||||
new_const = change_constant_precision<element::Type_t::i64, element::Type_t::i32>(constant);
|
||||
} else if (from == element::u8 && to == element::i32) {
|
||||
new_const = change_constant_precision<element::Type_t::u8, element::Type_t::i32>(constant);
|
||||
} else if (from == element::u16 && to == element::i32) {
|
||||
new_const = change_constant_precision<element::Type_t::u16, element::Type_t::i32>(constant);
|
||||
} else if (from == element::i16 && to == element::i32) {
|
||||
new_const = change_constant_precision<element::Type_t::i16, element::Type_t::i32>(constant);
|
||||
} else if (from == element::u32 && to == element::i32) {
|
||||
new_const = change_constant_precision<element::Type_t::u32, element::Type_t::i32>(constant);
|
||||
} else if (from == element::f64 && to == element::f32) {
|
||||
new_const = change_constant_precision<element::Type_t::f64, element::Type_t::f32>(constant);
|
||||
} else if (from == element::f16 && to == element::f32) {
|
||||
new_const = change_constant_precision<element::Type_t::f16, element::Type_t::f32>(constant);
|
||||
} else if (from == element::boolean && to == element::u8) {
|
||||
new_const = change_constant_precision<element::Type_t::boolean, element::Type_t::u8>(constant);
|
||||
} else if (from == element::boolean && to == element::i32) {
|
||||
new_const = change_constant_precision<element::Type_t::boolean, element::Type_t::i32>(constant);
|
||||
} else if (from == element::i4 || from == element::u4 || from == element::u1) {
|
||||
new_const = convert_low_precisions_int(constant, to);
|
||||
} else {
|
||||
throw ngraph_error("Precision conversion from " + from.get_type_name() + " to " + to.get_type_name() + " is not supported");
|
||||
}
|
||||
for (auto & output : consumers) {
|
||||
output.replace_source_output(new_const);
|
||||
}
|
||||
|
||||
new_const->validate_and_infer_types();
|
||||
new_const->set_friendly_name(constant->get_friendly_name());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -22,6 +22,7 @@ The target is able to take the following command-line arguments:
|
||||
* `--input_folders` specifies folders with IRs to run. The separator is `,`.
|
||||
* `--plugin_lib_name` is name of plugin library. The example is MKLDNNPlugin. Use only with unregistered in IE Core devices.
|
||||
* `--disable_test_config` allows to ignore all skipped tests with the exception of `DISABLED_` prefix using.
|
||||
* `--skip_config_path` allows to specify paths to files contain regular expressions list to skip tests.
|
||||
* `--extend_report` allows not to re-write device results to the report (add results of this run to the existing). Mutually exclusive with --report_unique_name.
|
||||
* `--report_unique_name` allows to save report with unique name (report_pid_timestamp.xml). Mutually exclusive with --extend_report.
|
||||
* `--save_report_timeout` allows to try to save report in cycle using timeout (in seconds).
|
||||
|
||||
+1
@@ -7,5 +7,6 @@ namespace ConformanceTests {
|
||||
extern const char* targetDevice;
|
||||
extern const char* targetPluginName;
|
||||
extern std::vector<std::string> IRFolderPaths;
|
||||
extern std::vector<std::string> disabledTests;
|
||||
|
||||
} // namespace ConformanceTests
|
||||
+4
@@ -23,12 +23,15 @@ static const char report_unique_name_message[] = "Optional. Allow to save report
|
||||
"Mutually exclusive with --extend_report. Default value is false";
|
||||
static const char save_report_timeout_message[] = "Optional. Allow to try to save report in cycle using timeout (in seconds). "
|
||||
"Default value is 60 seconds";
|
||||
static const char skip_config_path_message[] = "Optional. Allows to specify paths to files contain regular expressions list to skip tests. "
|
||||
"Delimiter is `,` symbol. Default value is empty string.";
|
||||
|
||||
DEFINE_bool(h, false, help_message);
|
||||
DEFINE_string(device, "CPU", target_device_message);
|
||||
DEFINE_string(plugin_lib_name, "", target_plugin_message);
|
||||
DEFINE_string(input_folders, ".", input_folders_message);
|
||||
DEFINE_string(output_folder, ".", output_folder_message);
|
||||
DEFINE_string(skip_config_path, "", skip_config_path_message);
|
||||
DEFINE_uint32(save_report_timeout, 60, save_report_timeout_message);
|
||||
DEFINE_bool(disable_test_config, true, disable_test_config_message);
|
||||
DEFINE_bool(extend_report, false, extend_report_config_message);
|
||||
@@ -44,6 +47,7 @@ static void showUsage() {
|
||||
std::cout << std::endl;
|
||||
std::cout << " -h " << help_message << std::endl;
|
||||
std::cout << " --disable_test_config " << disable_test_config_message << std::endl;
|
||||
std::cout << " --skip_config_path \"<paths>\" " << disable_test_config_message << std::endl;
|
||||
std::cout << " --extend_report " << extend_report_config_message << std::endl;
|
||||
std::cout << " --report_unique_name " << extend_report_config_message << std::endl;
|
||||
std::cout << " --save_report_timeout " << extend_report_config_message << std::endl;
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
# Hung:
|
||||
.*AvgPool_1199829.*
|
||||
.*AvgPool_1201153.*
|
||||
.*ROIPooling_1199827.*
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# Lost results
|
||||
.*Add_1087636.*
|
||||
.*Add_2868.*
|
||||
.*Add_2979.*
|
||||
.*Add_53543.*
|
||||
|
||||
# hung
|
||||
.*Concat_535028.*
|
||||
.*Concat_377139.*
|
||||
.*Concat_379481.*
|
||||
.*Concat_539044.*
|
||||
.*Concat_539074.*
|
||||
.*Concat_534956.*
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# TODO: Issue: 53062
|
||||
.*TensorIterator_1195103.*
|
||||
.*TensorIterator_1195129.*
|
||||
.*TensorIterator_1653010.*
|
||||
.*TensorIterator_199835.*
|
||||
.*TensorIterator_303641.*
|
||||
.*TensorIterator_303667.*
|
||||
.*TensorIterator_337260.*
|
||||
.*TensorIterator_362846.*
|
||||
.*TensorIterator_362869.*
|
||||
.*TensorIterator_362906.*
|
||||
.*TensorIterator_365496.*
|
||||
.*TensorIterator_365522.*
|
||||
.*TensorIterator_365556.*
|
||||
.*TensorIterator_365579.*
|
||||
.*TensorIterator_616544.*
|
||||
.*TensorIterator_616570.*
|
||||
.*TensorIterator_864978.*
|
||||
.*TensorIterator_865004.*
|
||||
.*TensorIterator_865030.*
|
||||
.*TensorIterator_865056.*
|
||||
.*TensorIterator_865082.*
|
||||
.*TensorIterator_865108.*
|
||||
.*TensorIterator_972832.*
|
||||
.*TensorIterator_972858.*
|
||||
.*TensorIterator_972884.*
|
||||
.*TensorIterator_972910.*
|
||||
.*TensorIterator_972936.*
|
||||
.*TensorIterator_972962.*
|
||||
.*TensorIterator_972988.*
|
||||
.*TensorIterator_973014.*
|
||||
.*TensorIterator_1194007.*
|
||||
.*TensorIterator_1194033.*
|
||||
.*TensorIterator_302500.*
|
||||
.*TensorIterator_337024.*
|
||||
.*TensorIterator_361044.*
|
||||
.*TensorIterator_361067.*
|
||||
.*TensorIterator_361108.*
|
||||
.*TensorIterator_361131.*
|
||||
.*TensorIterator_364171.*
|
||||
.*TensorIterator_364197.*
|
||||
.*TensorIterator_364231.*
|
||||
.*TensorIterator_364254.*
|
||||
.*TensorIterator_615626.*
|
||||
.*TensorIterator_615652.*
|
||||
.*TensorIterator_865760.*
|
||||
.*TensorIterator_865812.*
|
||||
.*TensorIterator_865838.*
|
||||
.*TensorIterator_865864.*
|
||||
.*TensorIterator_973781.*
|
||||
.*TensorIterator_973807.*
|
||||
|
||||
# Hung:
|
||||
.*AvgPool_1199829.*
|
||||
.*AvgPool_1201153.*
|
||||
.*GroupConvolution_330567.*
|
||||
.*ROIPooling_1199827.*
|
||||
.*MaxPool_43108.*
|
||||
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
# TODO: Issue: 53061
|
||||
.*ReduceMean_334003.*
|
||||
.*ReduceMean_334702.*
|
||||
.*Select_1172002.*
|
||||
.*Select_1178458.*
|
||||
.*Divide_567867.*
|
||||
.*Divide_1377278.*
|
||||
.*Divide_1030260.*
|
||||
.*Pad_274459.*
|
||||
.*Pad_276201.*
|
||||
.*Pad_276193.*
|
||||
.*Add_1070296.*
|
||||
.*Add_284191.*
|
||||
.*Add_1087636.*
|
||||
.*VariadicSplit_614428.*
|
||||
.*VariadicSplit_642662.*
|
||||
.*VariadicSplit_412430.*
|
||||
.*VariadicSplit_475191.*
|
||||
.*VariadicSplit_475203.*
|
||||
.*VariadicSplit_279359.*
|
||||
.*VariadicSplit_31490.*
|
||||
.*VariadicSplit_1444989.*
|
||||
.*VariadicSplit_31499.*
|
||||
.*VariadicSplit_279373.*
|
||||
.*VariadicSplit_279345.*
|
||||
.*VariadicSplit_31508.*
|
||||
.*VariadicSplit_535004.*
|
||||
.*VariadicSplit_148861.*
|
||||
.*VariadicSplit_475199.*
|
||||
.*VariadicSplit_412439.*
|
||||
.*VariadicSplit_412448.*
|
||||
.*VariadicSplit_475175.*
|
||||
.*VariadicSplit_427269.*
|
||||
.*VariadicSplit_1070300.*
|
||||
.*VariadicSplit_478455.*
|
||||
.*VariadicSplit_416024.*
|
||||
.*VariadicSplit_478469.*
|
||||
.*VariadicSplit_416006.*
|
||||
.*VariadicSplit_35108.*
|
||||
.*VariadicSplit_478473.*
|
||||
.*VariadicSplit_416015.*
|
||||
.*VariadicSplit_280446.*
|
||||
.*VariadicSplit_6686.*
|
||||
.*VariadicSplit_1087640.*
|
||||
.*VariadicSplit_1443292.*
|
||||
.*VariadicSplit_35099.*
|
||||
.*VariadicSplit_280460.*
|
||||
.*VariadicSplit_35090.*
|
||||
.*VariadicSplit_430827.*
|
||||
.*VariadicSplit_478461.*
|
||||
.*VariadicSplit_280432.*
|
||||
.*VariadicSplit_539066.*
|
||||
.*VariadicSplit_149040.*
|
||||
.*VariadicSplit_614761.*
|
||||
.*VariadicSplit_629649.*
|
||||
.*Unsqueeze_65214.*
|
||||
.*Unsqueeze_4838.*
|
||||
.*Unsqueeze_6661.*
|
||||
.*Multiply_65211.*
|
||||
.*Multiply_4833.*
|
||||
.*Multiply_48331.*
|
||||
.*Multiply_6656.*
|
||||
.*Subtract_534968.*
|
||||
.*Subtract_567907.*
|
||||
.*Gather_21153.*
|
||||
.*Gather_302464.*
|
||||
.*Gather_588814.*
|
||||
.*Gather_588810.*
|
||||
.*Gather_952843.*
|
||||
.*Gather_588818.*
|
||||
.*Gather_588871.*
|
||||
.*Gather_48276.*
|
||||
.*Gather_1652589.*
|
||||
.*Gather_535000.*
|
||||
.*Gather_360953.*
|
||||
.*Gather_588867.*
|
||||
.*Gather_48283.*
|
||||
.*Gather_1311696.*
|
||||
.*Gather_588796.*
|
||||
.*Gather_4847.*
|
||||
.*Gather_4803.*
|
||||
.*Gather_284209.*
|
||||
.*Gather_4869.*
|
||||
.*Gather_97426.*
|
||||
.*Gather_360963.*
|
||||
.*Gather_1570871.*
|
||||
.*Gather_513092.*
|
||||
.*Gather_629616.*
|
||||
.*Gather_48287.*
|
||||
.*Gather_284215.*
|
||||
.*Gather_48335.*
|
||||
.*Gather_1444.*
|
||||
.*Gather_4810.*
|
||||
.*Gather_1395.*
|
||||
.*Gather_1653002.*
|
||||
.*Gather_53520.*
|
||||
.*Gather_567864.*
|
||||
.*Gather_362776.*
|
||||
.*Gather_567856.*
|
||||
.*Gather_567919.*
|
||||
.*Gather_567830.*
|
||||
.*Gather_567923.*
|
||||
.*Gather_567860.*
|
||||
.*Gather_539062.*
|
||||
.*Gather_1304430.*
|
||||
.*Gather_938915.*
|
||||
.*Gather_53527.*
|
||||
.*Convert_284211.*
|
||||
.*Convert_4830.*
|
||||
.*Convert_567844.*
|
||||
.*Convert_6653.*
|
||||
.*FakeQuantize_738613.*
|
||||
.*FakeQuantize_738639.*
|
||||
.*Split_65164.*
|
||||
.*Split_274446.*
|
||||
.*Split_361038.*
|
||||
.*Split_330570.*
|
||||
.*Split_276188.*
|
||||
.*Split_68625.*
|
||||
.*Split_333279.*
|
||||
.*Split_362843.*
|
||||
.*Split_68647.*
|
||||
.*Floor_6658.*
|
||||
.*TopK_1172093.*
|
||||
.*TopK_1172038.*
|
||||
.*TopK_1178526.*
|
||||
.*TopK_515250.*
|
||||
.*TopK_1178477.*
|
||||
.*Reshape_1105704.*
|
||||
.*Reshape_1118646.*
|
||||
.*Reshape_588858.*
|
||||
.*Reshape_567910.*
|
||||
|
||||
# TODO: Crashes: Should be handled
|
||||
.*CTCGreedyDecoderSeqLen_271798.*
|
||||
.*MVN_276196.*
|
||||
.*MVN_274454.*
|
||||
|
||||
# hung
|
||||
.*Clamp_1178483.*
|
||||
|
||||
# lost results
|
||||
.*Add_1087636.*
|
||||
.*Add_2868.*
|
||||
.*Add_2979.*
|
||||
.*Add_53543.*
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
# hung
|
||||
.*AvgPool_1199829.*
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "common_test_utils/file_utils.hpp"
|
||||
#include "functional_test_utils/skip_tests_config.hpp"
|
||||
#include "shared_test_classes/base/layer_test_utils.hpp"
|
||||
|
||||
#include "gflag_config.hpp"
|
||||
@@ -45,6 +46,10 @@ int main(int argc, char* argv[]) {
|
||||
if (!FLAGS_plugin_lib_name.empty()) {
|
||||
ConformanceTests::targetPluginName = FLAGS_plugin_lib_name.c_str();
|
||||
}
|
||||
if (!FLAGS_skip_config_path.empty()) {
|
||||
ConformanceTests::disabledTests = FuncTestUtils::SkipTestsConfig::readSkipTestConfigFiles(
|
||||
CommonTestUtils::splitStringByDelimiter(FLAGS_skip_config_path));
|
||||
}
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
::testing::AddGlobalTestEnvironment(new LayerTestsUtils::TestEnvironment);
|
||||
|
||||
+3
-1
@@ -10,9 +10,11 @@ namespace ConformanceTests {
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
const char* targetDevice = "";
|
||||
std::vector<std::string> IRFolderPaths = {};
|
||||
const char* targetPluginName = "";
|
||||
|
||||
std::vector<std::string> IRFolderPaths = {};
|
||||
std::vector<std::string> disabledTests = {};
|
||||
|
||||
namespace {
|
||||
INSTANTIATE_TEST_CASE_P(conformance,
|
||||
ReadIRTest,
|
||||
|
||||
+1
-89
@@ -12,93 +12,5 @@
|
||||
#include "functional_test_utils/skip_tests_config.hpp"
|
||||
|
||||
std::vector<std::string> disabledTestPatterns() {
|
||||
std::vector<std::string> skippedTestsRegExp;
|
||||
std::string targetDevice = ConformanceTests::targetDevice;
|
||||
if (targetDevice.find(CommonTestUtils::DEVICE_MYRIAD) != std::string::npos) {
|
||||
std::vector<std::string> myriadSkips{
|
||||
// TODO: Issue: 53061
|
||||
R"(.*ReduceMean_334003.*)", R"(.*ReduceMean_334702.*)", R"(.*Select_1172002.*)", R"(.*Select_1178458.*)",
|
||||
R"(.*Divide_567867.*)", R"(.*Divide_1377278.*)", R"(.*Divide_1030260.*)", R"(.*Pad_274459.*)", R"(.*Pad_276201.*)",
|
||||
R"(.*Pad_276193.*)", R"(.*Add_1070296.*)", R"(.*Add_284191.*)", R"(.*Add_1087636.*)", R"(.*VariadicSplit_614428.*)",
|
||||
R"(.*VariadicSplit_642662.*)", R"(.*VariadicSplit_412430.*)", R"(.*VariadicSplit_475191.*)", R"(.*VariadicSplit_475203.*)",
|
||||
R"(.*VariadicSplit_279359.*)", R"(.*VariadicSplit_31490.*)", R"(.*VariadicSplit_1444989.*)", R"(.*VariadicSplit_31499.*)",
|
||||
R"(.*VariadicSplit_279373.*)", R"(.*VariadicSplit_279345.*)", R"(.*VariadicSplit_31508.*)", R"(.*VariadicSplit_535004.*)",
|
||||
R"(.*VariadicSplit_148861.*)", R"(.*VariadicSplit_475199.*)", R"(.*VariadicSplit_412439.*)", R"(.*VariadicSplit_412448.*)",
|
||||
R"(.*VariadicSplit_475175.*)", R"(.*VariadicSplit_427269.*)", R"(.*VariadicSplit_1070300.*)", R"(.*VariadicSplit_478455.*)",
|
||||
R"(.*VariadicSplit_416024.*)", R"(.*VariadicSplit_478469.*)", R"(.*VariadicSplit_416006.*)", R"(.*VariadicSplit_35108.*)",
|
||||
R"(.*VariadicSplit_478473.*)", R"(.*VariadicSplit_416015.*)", R"(.*VariadicSplit_280446.*)", R"(.*VariadicSplit_6686.*)",
|
||||
R"(.*VariadicSplit_1087640.*)", R"(.*VariadicSplit_1443292.*)", R"(.*VariadicSplit_35099.*)", R"(.*VariadicSplit_280460.*)",
|
||||
R"(.*VariadicSplit_35090.*)", R"(.*VariadicSplit_430827.*)", R"(.*VariadicSplit_478461.*)", R"(.*VariadicSplit_280432.*)",
|
||||
R"(.*VariadicSplit_539066.*)", R"(.*VariadicSplit_149040.*)", R"(.*VariadicSplit_614761.*)", R"(.*VariadicSplit_629649.*)",
|
||||
R"(.*Unsqueeze_65214.*)", R"(.*Unsqueeze_4838.*)", R"(.*Unsqueeze_6661.*)", R"(.*Multiply_65211.*)", R"(.*Multiply_4833.*)",
|
||||
R"(.*Multiply_48331.*)", R"(.*Multiply_6656.*)", R"(.*Subtract_534968.*)", R"(.*Subtract_567907.*)", R"(.*Gather_21153.*)",
|
||||
R"(.*Gather_302464.*)", R"(.*Gather_588814.*)", R"(.*Gather_588810.*)", R"(.*Gather_952843.*)", R"(.*Gather_588818.*)",
|
||||
R"(.*Gather_588871.*)", R"(.*Gather_48276.*)", R"(.*Gather_1652589.*)", R"(.*Gather_535000.*)", R"(.*Gather_360953.*)",
|
||||
R"(.*Gather_588867.*)", R"(.*Gather_48283.*)", R"(.*Gather_1311696.*)", R"(.*Gather_588796.*)", R"(.*Gather_4847.*)",
|
||||
R"(.*Gather_4803.*)", R"(.*Gather_284209.*)", R"(.*Gather_4869.*)", R"(.*Gather_97426.*)", R"(.*Gather_360963.*)", R"(.*Gather_1570871.*)",
|
||||
R"(.*Gather_513092.*)", R"(.*Gather_629616.*)", R"(.*Gather_48287.*)", R"(.*Gather_284215.*)", R"(.*Gather_48335.*)", R"(.*Gather_1444.*)",
|
||||
R"(.*Gather_4810.*)", R"(.*Gather_1395.*)", R"(.*Gather_1653002.*)", R"(.*Gather_53520.*)", R"(.*Gather_567864.*)", R"(.*Gather_362776.*)",
|
||||
R"(.*Gather_567856.*)", R"(.*Gather_567919.*)", R"(.*Gather_567830.*)", R"(.*Gather_567923.*)", R"(.*Gather_567860.*)", R"(.*Gather_539062.*)",
|
||||
R"(.*Gather_1304430.*)", R"(.*Gather_938915.*)", R"(.*Gather_53527.*)", R"(.*Convert_284211.*)", R"(.*Convert_4830.*)", R"(.*Convert_567844.*)",
|
||||
R"(.*Convert_6653.*)", R"(.*FakeQuantize_738613.*)", R"(.*FakeQuantize_738639.*)", R"(.*Split_65164.*)", R"(.*Split_274446.*)",
|
||||
R"(.*Split_361038.*)", R"(.*Split_330570.*)", R"(.*Split_276188.*)", R"(.*Split_68625.*)", R"(.*Split_333279.*)", R"(.*Split_362843.*)",
|
||||
R"(.*Split_68647.*)", R"(.*Floor_6658.*)", R"(.*TopK_1172093.*)", R"(.*TopK_1172038.*)", R"(.*TopK_1178526.*)", R"(.*TopK_515250.*)",
|
||||
R"(.*TopK_1178477.*)", R"(.*Reshape_1105704.*)", R"(.*Reshape_1118646.*)", R"(.*Reshape_588858.*)", R"(.*Reshape_567910.*)",
|
||||
// TODO: Crashes: Should be handled
|
||||
R"(.*CTCGreedyDecoderSeqLen_271798.*)", R"(.*MVN_276196.*)", R"(.*MVN_274454.*)",
|
||||
// hung
|
||||
R"(.*Clamp_1178483.*)",
|
||||
// lost results
|
||||
R"(.*Add_1087636.*)", R"(.*Add_2868.*)", R"(.*Add_2979.*)", R"(.*Add_53543.*)",
|
||||
};
|
||||
skippedTestsRegExp.insert(skippedTestsRegExp.end(),
|
||||
std::make_move_iterator(myriadSkips.begin()),
|
||||
std::make_move_iterator(myriadSkips.end()));
|
||||
}
|
||||
if (targetDevice.find(CommonTestUtils::DEVICE_GPU) != std::string::npos) {
|
||||
std::vector<std::string> gpuSkips{
|
||||
// TODO: Issue: 53062
|
||||
R"(.*TensorIterator_1195103.*)", R"(.*TensorIterator_1195129.*)", R"(.*TensorIterator_1653010.*)", R"(.*TensorIterator_199835.*)",
|
||||
R"(.*TensorIterator_303641.*)", R"(.*TensorIterator_303667.*)", R"(.*TensorIterator_337260.*)", R"(.*TensorIterator_362846.*)",
|
||||
R"(.*TensorIterator_362869.*)", R"(.*TensorIterator_362906.*)", R"(.*TensorIterator_365496.*)", R"(.*TensorIterator_365522.*)",
|
||||
R"(.*TensorIterator_365556.*)", R"(.*TensorIterator_365579.*)", R"(.*TensorIterator_616544.*)", R"(.*TensorIterator_616570.*)",
|
||||
R"(.*TensorIterator_864978.*)", R"(.*TensorIterator_865004.*)", R"(.*TensorIterator_865030.*)", R"(.*TensorIterator_865056.*)",
|
||||
R"(.*TensorIterator_865082.*)", R"(.*TensorIterator_865108.*)", R"(.*TensorIterator_972832.*)", R"(.*TensorIterator_972858.*)",
|
||||
R"(.*TensorIterator_972884.*)", R"(.*TensorIterator_972910.*)", R"(.*TensorIterator_972936.*)", R"(.*TensorIterator_972962.*)",
|
||||
R"(.*TensorIterator_972988.*)", R"(.*TensorIterator_973014.*)", R"(.*TensorIterator_1194007.*)", R"(.*TensorIterator_1194033.*)",
|
||||
R"(.*TensorIterator_302500.*)", R"(.*TensorIterator_337024.*)", R"(.*TensorIterator_361044.*)", R"(.*TensorIterator_361067.*)",
|
||||
R"(.*TensorIterator_361108.*)", R"(.*TensorIterator_361131.*)", R"(.*TensorIterator_364171.*)", R"(.*TensorIterator_364197.*)",
|
||||
R"(.*TensorIterator_364231.*)", R"(.*TensorIterator_364254.*)", R"(.*TensorIterator_615626.*)", R"(.*TensorIterator_615652.*)",
|
||||
R"(.*TensorIterator_865760.*)", R"(.*TensorIterator_865812.*)", R"(.*TensorIterator_865838.*)", R"(.*TensorIterator_865864.*)",
|
||||
R"(.*TensorIterator_973781.*)", R"(.*TensorIterator_973807.*)",
|
||||
// Hung:
|
||||
R"(.*AvgPool_1199829.*)", R"(.*AvgPool_1201153.*)", R"(.*GroupConvolution_330567.*)", R"(.*ROIPooling_1199827.*)",
|
||||
R"(.*MaxPool_43108.*)",
|
||||
};
|
||||
skippedTestsRegExp.insert(skippedTestsRegExp.end(),
|
||||
std::make_move_iterator(gpuSkips.begin()),
|
||||
std::make_move_iterator(gpuSkips.end()));
|
||||
}
|
||||
if (targetDevice.find(CommonTestUtils::DEVICE_CPU) != std::string::npos) {
|
||||
std::vector<std::string> cpuSkips{
|
||||
// Hung:
|
||||
R"(.*AvgPool_1199829.*)", R"(.*AvgPool_1201153.*)", R"(.*ROIPooling_1199827.*)",
|
||||
};
|
||||
skippedTestsRegExp.insert(skippedTestsRegExp.end(),
|
||||
std::make_move_iterator(cpuSkips.begin()),
|
||||
std::make_move_iterator(cpuSkips.end()));
|
||||
}
|
||||
if (targetDevice.find(CommonTestUtils::DEVICE_GNA) != std::string::npos) {
|
||||
std::vector<std::string> gnaSkips{
|
||||
// Lost results
|
||||
R"(.*Add_1087636.*)", R"(.*Add_2868.*)", R"(.*Add_2979.*)", R"(.*Add_53543.*)",
|
||||
// hung
|
||||
R"(.*Concat_535028.*)", R"(.*Concat_377139.*)", R"(.*Concat_379481.*)", R"(.*Concat_539044.*)", R"(.*Concat_539074.*)",
|
||||
R"(.*Concat_534956.*)",
|
||||
};
|
||||
skippedTestsRegExp.insert(skippedTestsRegExp.end(),
|
||||
std::make_move_iterator(gnaSkips.begin()),
|
||||
std::make_move_iterator(gnaSkips.end()));
|
||||
}
|
||||
return skippedTestsRegExp;
|
||||
return ConformanceTests::disabledTests;
|
||||
}
|
||||
+3
@@ -7,8 +7,10 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
std::vector<std::string> disabledTestPatterns();
|
||||
|
||||
namespace FuncTestUtils {
|
||||
@@ -17,6 +19,7 @@ namespace SkipTestsConfig {
|
||||
extern bool disable_tests_skipping;
|
||||
|
||||
bool currentTestIsDisabled();
|
||||
std::vector<std::string> readSkipTestConfigFiles(const std::vector<std::string>& filePaths);
|
||||
|
||||
} // namespace SkipTestsConfig
|
||||
} // namespace FuncTestUtils
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "common_test_utils/file_utils.hpp"
|
||||
#include "functional_test_utils/skip_tests_config.hpp"
|
||||
|
||||
namespace FuncTestUtils {
|
||||
@@ -21,5 +25,29 @@ bool currentTestIsDisabled() {
|
||||
return skip_test && !disable_tests_skipping;
|
||||
}
|
||||
|
||||
std::vector<std::string> readSkipTestConfigFiles(const std::vector<std::string>& filePaths) {
|
||||
std::vector<std::string> res;
|
||||
for (const auto& filePath : filePaths) {
|
||||
if (!CommonTestUtils::fileExists(filePath)) {
|
||||
std::string msg = "Input directory (" + filePath + ") doesn't not exist!";
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
std::ifstream file(filePath);
|
||||
if (file.is_open()) {
|
||||
std::string buffer;
|
||||
while (getline(file, buffer)) {
|
||||
if (buffer.find("#") == std::string::npos && !buffer.empty()) {
|
||||
res.emplace_back(buffer);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::string msg = "Error in opening file: " + filePath;
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace SkipTestsConfig
|
||||
} // namespace FuncTestUtils
|
||||
+4
@@ -56,6 +56,10 @@ class OpenCL2CHeaders(object):
|
||||
undefs += "#ifdef " + name + "\n"
|
||||
undefs += "#undef " + name + "\n"
|
||||
undefs += "#endif\n"
|
||||
if filename in self.include_files:
|
||||
for include_file in self.include_files[filename]:
|
||||
include_file_undefs = self.append_undefs(include_file)
|
||||
undefs += include_file_undefs
|
||||
return undefs
|
||||
|
||||
def append_file_content(self, filename, origin_file):
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from mo.front.common.replacement import FrontReplacementSubgraph
|
||||
from mo.graph.graph import Node, Graph
|
||||
from mo.utils.error import Error
|
||||
|
||||
|
||||
class SetPortsPattern(FrontReplacementSubgraph):
|
||||
@@ -28,6 +29,11 @@ class SetPortsPattern(FrontReplacementSubgraph):
|
||||
|
||||
in_ports_count = node.in_ports_count if node.has_valid('in_ports_count') else len(inputs)
|
||||
out_ports_count = node.out_ports_count if node.has_valid('out_ports_count') else len(outputs)
|
||||
|
||||
if len(outputs) > out_ports_count > 1:
|
||||
raise Error("Node {} has more children than it should: " +
|
||||
"should be {} but there is {}".format(node_id, out_ports_count, len(outputs)))
|
||||
|
||||
node['_in_ports'] = {}
|
||||
node['_out_ports'] = {}
|
||||
if in_ports_count is not None:
|
||||
|
||||
@@ -126,7 +126,8 @@ def load_kalid_nnet1_model(graph, file_descr, name):
|
||||
prev_layer_id = 'Parameter'
|
||||
graph.add_node(prev_layer_id, name=prev_layer_id, kind='op', op='Parameter', parameters=None)
|
||||
|
||||
used_layers = set()
|
||||
# find out output layer, it can be only one due to chain structure of nnet1 model
|
||||
output_layer = None
|
||||
while True:
|
||||
component_type = find_next_component(file_descr)
|
||||
if component_type == end_of_nnet_tag.lower()[1:-1]:
|
||||
@@ -158,8 +159,8 @@ def load_kalid_nnet1_model(graph, file_descr, name):
|
||||
prev_node.add_output_port(0)
|
||||
Node(graph, layer_id).add_input_port(0)
|
||||
graph.create_edge(prev_node, Node(graph, layer_id), 0, 0, create_edge_attrs(prev_layer_id, layer_id, prev_layer_id))
|
||||
used_layers.add(prev_layer_id)
|
||||
prev_layer_id = layer_id
|
||||
output_layer = layer_id
|
||||
log.debug('{} (type is {}) was loaded'.format(prev_layer_id, component_type))
|
||||
|
||||
# Tensor names information corresponding to a node is stored on outgoing edges.
|
||||
@@ -167,8 +168,8 @@ def load_kalid_nnet1_model(graph, file_descr, name):
|
||||
# for each output Identity node is added, and tensor name for the output is kept
|
||||
# on (output, fake output) edge. After Result nodes adding transformation fake outputs
|
||||
# are deleted from graph.
|
||||
output_layers = graph.nodes - used_layers
|
||||
add_outputs_identity(graph, output_layers, lambda g, output, fake_output: g.create_edge(
|
||||
assert output_layer is not None, "Output layer is not found in graph"
|
||||
add_outputs_identity(graph, [output_layer], lambda g, output, fake_output: g.create_edge(
|
||||
Node(g, output), Node(g, fake_output), 0, 0, create_edge_attrs(output, fake_output, output)))
|
||||
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ def parse_and_filter_versions_list(required_fw_versions, version_list, env_setup
|
||||
# check environment marker
|
||||
if len(splited_requirement) > 1:
|
||||
env_req = splited_requirement[1]
|
||||
splited_env_req = re.split(r"==|>=|<=|>|<", env_req)
|
||||
splited_env_req = re.split(r"==|>=|<=|>|<|~=", env_req)
|
||||
splited_env_req = [l.strip(',') for l in splited_env_req]
|
||||
env_marker = splited_env_req[0].strip(' ')
|
||||
if env_marker == 'python_version' and env_marker in env_setup:
|
||||
@@ -69,7 +69,7 @@ def parse_and_filter_versions_list(required_fw_versions, version_list, env_setup
|
||||
env_req_version_list = []
|
||||
splited_required_versions = re.split(r",", env_req)
|
||||
for i, l in enumerate(splited_required_versions):
|
||||
for comparison in ['==', '>=', '<=', '<', '>']:
|
||||
for comparison in ['==', '>=', '<=', '<', '>', '~=']:
|
||||
if comparison in l:
|
||||
required_version = splited_env_req[i + 1].strip(' ').replace('"', '')
|
||||
env_req_version_list.append((env_marker, comparison, required_version))
|
||||
@@ -88,7 +88,7 @@ def parse_and_filter_versions_list(required_fw_versions, version_list, env_setup
|
||||
|
||||
# parse a requirement for a dependency
|
||||
requirement = splited_requirement[0]
|
||||
splited_versions_by_conditions = re.split(r"==|>=|<=|>|<", requirement)
|
||||
splited_versions_by_conditions = re.split(r"==|>=|<=|>|<|~=", requirement)
|
||||
splited_versions_by_conditions = [l.strip(',') for l in splited_versions_by_conditions]
|
||||
|
||||
if len(splited_versions_by_conditions) == 0:
|
||||
@@ -98,7 +98,7 @@ def parse_and_filter_versions_list(required_fw_versions, version_list, env_setup
|
||||
else:
|
||||
splited_required_versions= re.split(r",", requirement)
|
||||
for i, l in enumerate(splited_required_versions):
|
||||
for comparison in ['==', '>=', '<=', '<', '>']:
|
||||
for comparison in ['==', '>=', '<=', '<', '>', '~=']:
|
||||
if comparison in l:
|
||||
version_list.append((splited_versions_by_conditions[0], comparison, splited_versions_by_conditions[i + 1]))
|
||||
break
|
||||
@@ -158,6 +158,15 @@ def version_check(name, installed_v, required_v, sign, not_satisfied_v):
|
||||
satisfied = installed_v < req_ver
|
||||
elif sign == '==':
|
||||
satisfied = installed_v == req_ver
|
||||
elif sign == '~=':
|
||||
req_ver_list = req_ver.vstring.split('.')
|
||||
if 'post' in req_ver_list[-1]:
|
||||
assert len(req_ver_list) >= 3, 'Error during {} module version checking: {} {} {}, please check ' \
|
||||
'required version of this module in requirements_*.txt file!'\
|
||||
.format(name, installed_v, sign, required_v)
|
||||
req_ver_list.pop(-1)
|
||||
idx = len(req_ver_list) - 1
|
||||
satisfied = installed_v >= req_ver and (installed_v.split('.')[:idx] == req_ver_list[:idx])
|
||||
else:
|
||||
log.error("Error during version comparison")
|
||||
else:
|
||||
|
||||
+18
-13
@@ -9,23 +9,22 @@ Use this script to create a wheel with Model Optimizer code:
|
||||
$ python setup.py sdist bdist_wheel
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
from shutil import copyfile
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools.command.install import install
|
||||
from setuptools.command.build_py import build_py
|
||||
from shutil import copyfile
|
||||
|
||||
package_name = 'mo'
|
||||
PACKAGE_NAME = 'mo'
|
||||
|
||||
# Detect all the framework specific requirements_*.txt files.
|
||||
requirements_txt = []
|
||||
py_modules = []
|
||||
for name in os.listdir():
|
||||
if re.match('requirements(.*)\.txt', name):
|
||||
if re.match(r'requirements(.*)\.txt', name):
|
||||
requirements_txt.append(name)
|
||||
if re.match('mo(.*)\.py', name):
|
||||
if re.match(r'mo(.*)\.py', name):
|
||||
py_modules.append(name.split('.')[0])
|
||||
|
||||
# Minimal set of dependencies
|
||||
@@ -42,22 +41,22 @@ class InstallCmd(install):
|
||||
install.run(self)
|
||||
# Create requirements.txt files for all the frameworks
|
||||
for name in requirements_txt:
|
||||
path = os.path.join(self.install_purelib, package_name, name)
|
||||
path = os.path.join(self.install_purelib, PACKAGE_NAME, name)
|
||||
with open(path, 'wt') as f:
|
||||
f.write('\n'.join(deps))
|
||||
# Add version.txt if exists
|
||||
version_txt = 'version.txt'
|
||||
if os.path.exists(version_txt):
|
||||
copyfile(os.path.join(version_txt),
|
||||
os.path.join(self.install_purelib, package_name, version_txt))
|
||||
|
||||
path = os.path.join(self.install_purelib, package_name, '__init__.py')
|
||||
os.path.join(self.install_purelib, PACKAGE_NAME, version_txt))
|
||||
|
||||
path = os.path.join(self.install_purelib, PACKAGE_NAME, '__init__.py')
|
||||
with open(path, 'wt') as f:
|
||||
f.write('import os, sys\n')
|
||||
f.write('from {} import mo\n'.format(package_name))
|
||||
f.write('from {} import mo\n'.format(PACKAGE_NAME))
|
||||
# This is required to fix internal imports
|
||||
f.write('sys.path.append(os.path.dirname(__file__))\n')
|
||||
# We install a package into custom folder "package_name".
|
||||
# We install a package into custom folder "PACKAGE_NAME".
|
||||
# Redirect import to model-optimizer/mo/__init__.py
|
||||
f.write('sys.modules["mo"] = mo')
|
||||
|
||||
@@ -73,7 +72,7 @@ class BuildCmd(build_py):
|
||||
|
||||
|
||||
packages = find_packages()
|
||||
packages = [package_name + '.' + p for p in packages]
|
||||
packages = [PACKAGE_NAME + '.' + p for p in packages]
|
||||
|
||||
setup(name='openvino-mo',
|
||||
version='0.0.0',
|
||||
@@ -81,7 +80,7 @@ setup(name='openvino-mo',
|
||||
author_email='openvino_pushbot@intel.com',
|
||||
url='https://github.com/openvinotoolkit/openvino',
|
||||
packages=packages,
|
||||
package_dir={package_name: '.'},
|
||||
package_dir={PACKAGE_NAME: '.'},
|
||||
py_modules=py_modules,
|
||||
cmdclass={
|
||||
'install': InstallCmd,
|
||||
@@ -92,6 +91,12 @@ setup(name='openvino-mo',
|
||||
'mo = mo.__main__:main',
|
||||
],
|
||||
},
|
||||
package_data={
|
||||
'mo.mo.front.caffe.proto': ['*.proto'],
|
||||
'mo.extensions.front.mxnet': ['*.json'],
|
||||
'mo.extensions.front.onnx': ['*.json'],
|
||||
'mo.extensions.front.tf': ['*.json'],
|
||||
},
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import unittest
|
||||
|
||||
from extensions.front.kaldi.set_ports import SetPortsPattern
|
||||
from mo.utils.error import Error
|
||||
from mo.utils.ir_engine.compare_graphs import compare_graphs
|
||||
from unit_tests.utils.graph import build_graph, regular_op, connect_front, Node
|
||||
|
||||
|
||||
class SetPortsTest(unittest.TestCase):
|
||||
def test_set_ports_chain(self):
|
||||
nodes = {
|
||||
**regular_op('op1', {}),
|
||||
**regular_op('op2', {}),
|
||||
**regular_op('op3', {}),
|
||||
}
|
||||
|
||||
graph = build_graph(nodes, [
|
||||
('op1', 'op2', {'fw_tensor_debug_info': {}}),
|
||||
('op2', 'op3', {'fw_tensor_debug_info': {}})
|
||||
], nodes_with_edges_only=True)
|
||||
|
||||
graph.stage = 'front'
|
||||
|
||||
ref_graph = build_graph(nodes, [
|
||||
*connect_front('op1:0', '0:op2'),
|
||||
*connect_front('op2:0', '0:op3')
|
||||
], nodes_with_edges_only=True)
|
||||
|
||||
SetPortsPattern().find_and_replace_pattern(graph)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, ref_graph, 'op3', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test_set_ports_split(self):
|
||||
nodes = {
|
||||
**regular_op('op1', {}),
|
||||
**regular_op('split', {'op': 'Split'}),
|
||||
**regular_op('op2', {}),
|
||||
**regular_op('op3', {}),
|
||||
**regular_op('op4', {}),
|
||||
}
|
||||
|
||||
graph = build_graph(nodes, [
|
||||
('op1', 'split', {'fw_tensor_debug_info': {}}),
|
||||
('split', 'op2', {'fw_tensor_debug_info': {}, 'out_port': 0}),
|
||||
('split', 'op3', {'fw_tensor_debug_info': {}, 'out_port': 1}),
|
||||
('split', 'op4', {'fw_tensor_debug_info': {}, 'out_port': 2})
|
||||
], nodes_with_edges_only=True)
|
||||
|
||||
graph.stage = 'front'
|
||||
graph.nodes()['split']['out_ports_count'] = 3
|
||||
|
||||
ref_graph = build_graph(nodes, [
|
||||
*connect_front('op1:0', '0:split'),
|
||||
*connect_front('split:0', '0:op2'),
|
||||
*connect_front('split:1', '0:op3'),
|
||||
*connect_front('split:2', '0:op4')
|
||||
], nodes_with_edges_only=True)
|
||||
|
||||
SetPortsPattern().find_and_replace_pattern(graph)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, ref_graph, 'op4', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test_set_ports_split2(self):
|
||||
nodes = {
|
||||
**regular_op('op1', {}),
|
||||
**regular_op('split', {'op': 'Split'}),
|
||||
**regular_op('op2', {}),
|
||||
**regular_op('op3', {}),
|
||||
**regular_op('op4', {}),
|
||||
}
|
||||
|
||||
graph = build_graph(nodes, [
|
||||
('op1', 'split', {'fw_tensor_debug_info': {}}),
|
||||
('split', 'op2', {'fw_tensor_debug_info': {}, 'out_port': 0}),
|
||||
('split', 'op4', {'fw_tensor_debug_info': {}, 'out_port': 4}),
|
||||
('split', 'op3', {'fw_tensor_debug_info': {}, 'out_port': 6})
|
||||
], nodes_with_edges_only=True)
|
||||
|
||||
graph.stage = 'front'
|
||||
graph.nodes()['split']['out_ports_count'] = 3
|
||||
|
||||
ref_graph = build_graph(nodes, [
|
||||
*connect_front('op1:0', '0:split'),
|
||||
*connect_front('split:0', '0:op2'),
|
||||
*connect_front('split:1', '0:op4'),
|
||||
*connect_front('split:2', '0:op3')
|
||||
], nodes_with_edges_only=True)
|
||||
|
||||
SetPortsPattern().find_and_replace_pattern(graph)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, ref_graph, 'op4', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test_set_ports_split3(self):
|
||||
nodes = {
|
||||
**regular_op('op1', {}),
|
||||
**regular_op('split', {'op': 'Split'}),
|
||||
**regular_op('op2', {}),
|
||||
**regular_op('op3', {}),
|
||||
**regular_op('op4', {}),
|
||||
}
|
||||
|
||||
graph = build_graph(nodes, [
|
||||
('op1', 'split', {'fw_tensor_debug_info': {}}),
|
||||
('split', 'op2', {'fw_tensor_debug_info': {}, 'out_port': 0}),
|
||||
('split', 'op3', {'fw_tensor_debug_info': {}, 'out_port': 1}),
|
||||
('split', 'op4', {'fw_tensor_debug_info': {}, 'out_port': 2})
|
||||
], nodes_with_edges_only=True)
|
||||
|
||||
Node(graph, 'split').out_port(0).get_connection().add_destination(Node(graph, 'op4').in_port(0))
|
||||
graph.nodes()['split']['out_ports_count'] = 2
|
||||
|
||||
graph.stage = 'front'
|
||||
|
||||
self.assertRaises(Error, SetPortsPattern().find_and_replace_pattern, graph)
|
||||
@@ -13,12 +13,19 @@ class TestingVersionsChecker(unittest.TestCase):
|
||||
def test_get_module_version_list_from_file(self, mock_open):
|
||||
mock_open.return_value.__enter__ = mock_open
|
||||
mock_open.return_value.__iter__ = mock.Mock(
|
||||
return_value=iter(['mxnet>=1.0.0,<=1.3.1', 'networkx>=1.11', 'numpy==1.12.0', 'defusedxml<=0.5.0']))
|
||||
ref_list =[('mxnet', '>=', '1.0.0'), ('mxnet', '<=', '1.3.1'),
|
||||
('networkx', '>=', '1.11'),
|
||||
('numpy', '==', '1.12.0'), ('defusedxml', '<=', '0.5.0')]
|
||||
return_value=iter(['mxnet>=1.0.0,<=1.3.1',
|
||||
'networkx>=1.11',
|
||||
'numpy==1.12.0',
|
||||
'defusedxml<=0.5.0',
|
||||
'networkx~=1.11']))
|
||||
ref_list = [('mxnet', '>=', '1.0.0'),
|
||||
('mxnet', '<=', '1.3.1'),
|
||||
('networkx', '>=', '1.11'),
|
||||
('numpy', '==', '1.12.0'),
|
||||
('defusedxml', '<=', '0.5.0'),
|
||||
('networkx', '~=', '1.11')]
|
||||
version_list = get_module_version_list_from_file('mock_file', {})
|
||||
self.assertEqual(len(version_list), 5)
|
||||
self.assertEqual(len(version_list), 6)
|
||||
for i, version_dict in enumerate(version_list):
|
||||
self.assertTupleEqual(ref_list[i], version_dict)
|
||||
|
||||
@@ -29,13 +36,15 @@ class TestingVersionsChecker(unittest.TestCase):
|
||||
return_value=iter(['tensorflow>=1.15.2,<2.0; python_version < "3.8"',
|
||||
'tensorflow>=2.0; python_version >= "3.8"',
|
||||
'numpy==1.12.0',
|
||||
'defusedxml<=0.5.0']))
|
||||
ref_list =[('tensorflow', '>=', '1.15.2'),
|
||||
('tensorflow', '<', '2.0'),
|
||||
('numpy', '==', '1.12.0'),
|
||||
('defusedxml', '<=', '0.5.0')]
|
||||
'defusedxml<=0.5.0',
|
||||
'networkx~=1.11']))
|
||||
ref_list = [('tensorflow', '>=', '1.15.2'),
|
||||
('tensorflow', '<', '2.0'),
|
||||
('numpy', '==', '1.12.0'),
|
||||
('defusedxml', '<=', '0.5.0'),
|
||||
('networkx', '~=', '1.11')]
|
||||
version_list = get_module_version_list_from_file('mock_file', {'python_version': '3.7.0'})
|
||||
self.assertEqual(len(version_list), 4)
|
||||
self.assertEqual(len(version_list), 5)
|
||||
for i, version_dict in enumerate(version_list):
|
||||
self.assertTupleEqual(ref_list[i], version_dict)
|
||||
|
||||
@@ -46,12 +55,14 @@ class TestingVersionsChecker(unittest.TestCase):
|
||||
return_value=iter(['tensorflow>=1.15.2,<2.0; python_version < "3.8"',
|
||||
'tensorflow>=2.0; python_version >= "3.8"',
|
||||
'numpy==1.12.0',
|
||||
'defusedxml<=0.5.0']))
|
||||
ref_list =[('tensorflow', '>=', '2.0'),
|
||||
('numpy', '==', '1.12.0'),
|
||||
('defusedxml', '<=', '0.5.0')]
|
||||
'defusedxml<=0.5.0',
|
||||
'networkx~=1.11']))
|
||||
ref_list = [('tensorflow', '>=', '2.0'),
|
||||
('numpy', '==', '1.12.0'),
|
||||
('defusedxml', '<=', '0.5.0'),
|
||||
('networkx', '~=', '1.11')]
|
||||
version_list = get_module_version_list_from_file('mock_file', {'python_version': '3.8.1'})
|
||||
self.assertEqual(len(version_list), 3)
|
||||
self.assertEqual(len(version_list), 4)
|
||||
for i, version_dict in enumerate(version_list):
|
||||
self.assertTupleEqual(ref_list[i], version_dict)
|
||||
|
||||
@@ -110,9 +121,11 @@ class TestingVersionsChecker(unittest.TestCase):
|
||||
('module_2', '>=', '1.12.0', '1.12.0'),
|
||||
('module_3', '>=', '1.12.0', '1.12.1'),
|
||||
('module_4', '>=', '1.12.0', '1.20.0'),
|
||||
('module_5', '>=', '1.12.0.post2', '1.12.0.post1'),
|
||||
]
|
||||
|
||||
ref_list = [('module_1', 'installed: 1.09.2', 'required: >= 1.12.0')
|
||||
ref_list = [('module_1', 'installed: 1.09.2', 'required: >= 1.12.0'),
|
||||
('module_5', 'installed: 1.12.0.post1', 'required: >= 1.12.0.post2')
|
||||
]
|
||||
|
||||
not_satisfied_versions = []
|
||||
@@ -126,6 +139,7 @@ class TestingVersionsChecker(unittest.TestCase):
|
||||
('module_2', '<', '1.11', '1.10.1'),
|
||||
('module_3', '<', '1.11', '1.11'),
|
||||
('module_4', '<', '1.11', '1.20'),
|
||||
('module_5', '<', '1.11', '1.10.post2'),
|
||||
]
|
||||
|
||||
ref_list = [('module_3', 'installed: 1.11', 'required: < 1.11'),
|
||||
@@ -154,3 +168,29 @@ class TestingVersionsChecker(unittest.TestCase):
|
||||
for name, key, required_version, installed_version in modules_versions_list:
|
||||
version_check(name, installed_version, required_version, key, not_satisfied_versions)
|
||||
self.assertEqual(not_satisfied_versions, ref_list)
|
||||
|
||||
def test_version_check_compatible(self):
|
||||
modules_versions_list = [('module_1', '~=', '1.2.3', '1.2.3'),
|
||||
('module_2', '~=', '1.2.3', '1.2.3b4'),
|
||||
('module_3', '~=', '1.2.3', '1.2.4'),
|
||||
('module_4', '~=', '1.2.3', '1.3.0'),
|
||||
('module_5', '~=', '1.2.3', '1.2.2'),
|
||||
('module_6', '~=', '1.2.3', '2.2.2'),
|
||||
('module_7', '~=', '1.2.post2', '1.3'),
|
||||
('module_8', '~=', '1.2.post2', '1.2'),
|
||||
('module_9', '~=', '1.2.post2', '1.2.post1'),
|
||||
('module_9', '~=', '1.2.post2', '1.2.post4')
|
||||
]
|
||||
|
||||
ref_list = [('module_4', 'installed: 1.3.0', 'required: ~= 1.2.3'),
|
||||
('module_5', 'installed: 1.2.2', 'required: ~= 1.2.3'),
|
||||
('module_6', 'installed: 2.2.2', 'required: ~= 1.2.3'),
|
||||
('module_8', 'installed: 1.2', 'required: ~= 1.2.post2'),
|
||||
('module_9', 'installed: 1.2.post1', 'required: ~= 1.2.post2')
|
||||
]
|
||||
|
||||
not_satisfied_versions = []
|
||||
|
||||
for name, key, required_version, installed_version in modules_versions_list:
|
||||
version_check(name, installed_version, required_version, key, not_satisfied_versions)
|
||||
self.assertEqual(not_satisfied_versions, ref_list)
|
||||
@@ -23,6 +23,7 @@ FetchContent_Declare(
|
||||
ext_onnx
|
||||
GIT_REPOSITORY ${ONNX_GIT_REPO_URL}
|
||||
GIT_TAG ${ONNX_GIT_BRANCH}
|
||||
GIT_SHALLOW TRUE
|
||||
# apply patch to fix problems with symbols visibility for MSVC
|
||||
PATCH_COMMAND git reset --hard HEAD && git apply --ignore-space-change --ignore-whitespace --verbose ${ONNX_PATCH_FILE}
|
||||
)
|
||||
|
||||
@@ -68,6 +68,7 @@ else()
|
||||
ext_protobuf
|
||||
GIT_REPOSITORY ${NGRAPH_PROTOBUF_GIT_REPO_URL}
|
||||
GIT_TAG ${NGRAPH_PROTOBUF_GIT_TAG}
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(ext_protobuf)
|
||||
|
||||
@@ -72,6 +72,11 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set_target_properties(ngraph PROPERTIES LINK_FLAGS "/IGNORE:4217,4286")
|
||||
endif()
|
||||
|
||||
set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/src/pass/convert_precision.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/pass/convert_fp32_to_fp16.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/op/type_relaxed.cpp"
|
||||
PROPERTIES INCLUDE_DIRECTORIES $<TARGET_PROPERTY:inference_engine_transformations,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
|
||||
# Defines macro in C++ to load backend plugin
|
||||
target_include_directories(ngraph PUBLIC $<BUILD_INTERFACE:${NGRAPH_INCLUDE_PATH}>
|
||||
$<INSTALL_INTERFACE:${NGRAPH_INSTALL_INCLUDE}>
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace ngraph
|
||||
}
|
||||
constexpr const char* get_ptr(size_t offset) const
|
||||
{
|
||||
return offset < m_size ? &m_string[offset] : nullptr;
|
||||
return offset < m_size ? &m_string[offset] : m_string;
|
||||
}
|
||||
constexpr size_t size() const { return m_size; }
|
||||
|
||||
|
||||
@@ -10,21 +10,11 @@ namespace ngraph
|
||||
{
|
||||
namespace pass
|
||||
{
|
||||
class NGRAPH_API ConvertFP32ToFP16 : public ngraph::pass::GraphRewrite
|
||||
class NGRAPH_API ConvertFP32ToFP16 : public ngraph::pass::FunctionPass
|
||||
{
|
||||
public:
|
||||
NGRAPH_RTTI_DECLARATION;
|
||||
ConvertFP32ToFP16()
|
||||
: GraphRewrite()
|
||||
{
|
||||
convert_constants_precision();
|
||||
convert_parameters_precision();
|
||||
}
|
||||
|
||||
private:
|
||||
void convert_constants_precision();
|
||||
|
||||
void convert_parameters_precision();
|
||||
bool run_on_function(std::shared_ptr<ngraph::Function>) override;
|
||||
};
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
@@ -162,27 +162,29 @@ bool op::v1::ConvolutionBackpropData::is_dynamic() const
|
||||
const PartialShape op::v1::ConvolutionBackpropData::get_output_shape() const
|
||||
{
|
||||
auto data_pshape = get_input_partial_shape(0);
|
||||
auto filter_pshape = get_input_partial_shape(1);
|
||||
|
||||
PartialShape shape;
|
||||
bool is_output_shape_present = inputs().size() == 3;
|
||||
if (is_output_shape_present)
|
||||
{
|
||||
if (const auto& const_op = get_constant_from_source(input_value(2)))
|
||||
{
|
||||
return PartialShape{const_op->get_shape_val()};
|
||||
}
|
||||
}
|
||||
|
||||
if (data_pshape.rank().is_static())
|
||||
{
|
||||
shape = PartialShape{vector<Dimension>(data_pshape.rank().get_length() - 2)};
|
||||
}
|
||||
else if (filter_pshape.rank().is_static())
|
||||
{
|
||||
shape = PartialShape{vector<Dimension>(filter_pshape.rank().get_length() - 2)};
|
||||
}
|
||||
else
|
||||
{
|
||||
shape = PartialShape{vector<Dimension>(m_strides.size())};
|
||||
}
|
||||
bool is_output_shape_present = inputs().size() == 3;
|
||||
if (is_output_shape_present)
|
||||
{
|
||||
if (auto const_op = get_constant_from_source(input_value(2)))
|
||||
{
|
||||
shape = const_op->get_shape_val();
|
||||
}
|
||||
else
|
||||
{
|
||||
shape = PartialShape::dynamic();
|
||||
}
|
||||
shape = PartialShape::dynamic();
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
@@ -230,14 +232,11 @@ void op::v1::ConvolutionBackpropData::infer_conv_backprop_output_spatial_shape(
|
||||
void op::v1::ConvolutionBackpropData::validate_and_infer_types()
|
||||
{
|
||||
NGRAPH_OP_SCOPE(v1_ConvolutionBackpropData_validate_and_infer_types);
|
||||
auto data_pshape = get_input_partial_shape(0);
|
||||
const PartialShape& data_pshape = get_input_partial_shape(0);
|
||||
element::Type delta_et = get_input_element_type(0);
|
||||
const PartialShape& filters_pshape = get_input_partial_shape(1);
|
||||
element::Type filters_et = get_input_element_type(1);
|
||||
|
||||
bool is_output_shape_present = inputs().size() == 3;
|
||||
PartialShape output_pshape = get_output_shape();
|
||||
|
||||
element::Type result_et;
|
||||
NODE_VALIDATION_CHECK(
|
||||
this,
|
||||
@@ -248,30 +247,81 @@ void op::v1::ConvolutionBackpropData::validate_and_infer_types()
|
||||
filters_et,
|
||||
").");
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
result_et.is_real() || result_et.is_integral_number(),
|
||||
"Element type of inputs must be numeric. Got: ",
|
||||
result_et);
|
||||
|
||||
Rank result_ps_rank;
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
Rank::merge(result_ps_rank, data_pshape.rank(), filters_pshape.rank()),
|
||||
"Data and filters inputs must have same rank. Got: ",
|
||||
data_pshape,
|
||||
" and ",
|
||||
filters_pshape);
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
result_ps_rank.compatible(3) || result_ps_rank.compatible(4) ||
|
||||
result_ps_rank.compatible(5),
|
||||
"Data and filters inputs must have rank 3, 4 or 5. Got: ",
|
||||
result_ps_rank);
|
||||
|
||||
if (data_pshape.rank().is_static() && filters_pshape.rank().is_static())
|
||||
{
|
||||
if (m_pads_begin.size() == 0)
|
||||
{
|
||||
m_pads_begin = conv_default_padding(this, data_pshape, filters_pshape);
|
||||
}
|
||||
if (m_pads_end.size() == 0)
|
||||
{
|
||||
m_pads_end = conv_default_padding(this, data_pshape, filters_pshape);
|
||||
}
|
||||
if (m_output_padding.size() == 0)
|
||||
{
|
||||
m_output_padding = conv_default_padding(this, data_pshape, filters_pshape);
|
||||
}
|
||||
NODE_VALIDATION_CHECK(
|
||||
this,
|
||||
data_pshape[1].compatible(filters_pshape[0]),
|
||||
"Input channels dimension of data and filters inputs must be equal. Got: ",
|
||||
data_pshape,
|
||||
" and ",
|
||||
filters_pshape);
|
||||
}
|
||||
|
||||
bool is_output_shape_present = inputs().size() == 3;
|
||||
if (is_output_shape_present)
|
||||
{
|
||||
const PartialShape& output_shape_pshape = get_input_partial_shape(2);
|
||||
const element::Type output_shape_et = get_input_element_type(2);
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
output_shape_et.is_integral_number(),
|
||||
"Element type for output shape should be of integer type ",
|
||||
"(output_shape element type: ",
|
||||
output_shape_et,
|
||||
").");
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
output_shape_pshape.rank().compatible(1),
|
||||
"Spatial shape of output input must be of rank 1 ",
|
||||
"(output_shape shape: ",
|
||||
output_shape_pshape,
|
||||
").");
|
||||
}
|
||||
PartialShape output_spatial_pshape = get_output_shape();
|
||||
|
||||
if (result_ps_rank.is_static())
|
||||
{
|
||||
const auto num_spatial_dims = result_ps_rank.get_length() - 2;
|
||||
if (m_strides.size() == 0)
|
||||
{
|
||||
m_strides = conv_default_strides(this, data_pshape, filters_pshape);
|
||||
m_strides = Strides(num_spatial_dims, 1);
|
||||
}
|
||||
if (m_dilations.size() == 0)
|
||||
{
|
||||
m_dilations = conv_default_strides(this, data_pshape, filters_pshape);
|
||||
m_dilations = Strides(num_spatial_dims, 1);
|
||||
}
|
||||
if (m_pads_begin.size() == 0 || m_auto_pad == PadType::VALID)
|
||||
{
|
||||
m_pads_begin = CoordinateDiff(num_spatial_dims, 0);
|
||||
}
|
||||
if (m_pads_end.size() == 0 || m_auto_pad == PadType::VALID)
|
||||
{
|
||||
m_pads_end = CoordinateDiff(num_spatial_dims, 0);
|
||||
}
|
||||
if (m_output_padding.size() == 0)
|
||||
{
|
||||
m_output_padding = CoordinateDiff(num_spatial_dims, 0);
|
||||
}
|
||||
|
||||
const auto num_spatial_dims = data_pshape.rank().get_length() - 2;
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
static_cast<int64_t>(m_strides.size()) == num_spatial_dims,
|
||||
@@ -281,48 +331,74 @@ void op::v1::ConvolutionBackpropData::validate_and_infer_types()
|
||||
static_cast<int64_t>(m_dilations.size()) == num_spatial_dims,
|
||||
"Dilations should be defined for all and only spatial features.");
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
static_cast<int64_t>(m_pads_begin.size()) == num_spatial_dims &&
|
||||
static_cast<int64_t>(m_pads_end.size()) == num_spatial_dims,
|
||||
"Pads should be defined for all and only spatial features.");
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
static_cast<int64_t>(m_output_padding.size()) == num_spatial_dims,
|
||||
"Output padding should be defined for all and only "
|
||||
"spatial features.");
|
||||
}
|
||||
|
||||
PartialShape result_shape;
|
||||
if (is_output_shape_present)
|
||||
{
|
||||
if (output_pshape.is_static() && filters_pshape.is_static() && data_pshape.is_static())
|
||||
if (is_output_shape_present && output_spatial_pshape.is_static())
|
||||
{
|
||||
Shape output_shape = output_pshape.to_shape();
|
||||
const Shape data_shape = data_pshape.to_shape();
|
||||
const Shape filters_shape = filters_pshape.to_shape();
|
||||
const size_t num_spatial_dims = data_shape.size() - 2;
|
||||
|
||||
Shape output_shape = output_spatial_pshape.to_shape();
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
output_shape.size() == num_spatial_dims,
|
||||
static_cast<int64_t>(output_shape.size()) == num_spatial_dims,
|
||||
"Output shape should be specified only and for "
|
||||
"all spatial dimensions.");
|
||||
}
|
||||
}
|
||||
|
||||
// If auto_pad has one of following mode we infer paddings. Otherwise in
|
||||
// EXPLICIT auto_pad mode we use what is provided.
|
||||
if (m_auto_pad == PadType::SAME_UPPER || m_auto_pad == PadType::SAME_LOWER)
|
||||
PartialShape result_pshape{PartialShape::dynamic()};
|
||||
// If output shape is provided, ignore current values for padding begin/end
|
||||
// and infer them.
|
||||
if (is_output_shape_present)
|
||||
{
|
||||
if (output_spatial_pshape.rank().is_static())
|
||||
{
|
||||
if (data_pshape.rank().is_static() && filters_pshape.rank().is_static())
|
||||
{
|
||||
opset1::infer_conv_backprop_auto_padding(
|
||||
Shape{std::next(data_shape.begin(), 2), std::end(data_shape)},
|
||||
Shape{std::next(filters_shape.begin(), 2), std::end(filters_shape)},
|
||||
output_shape,
|
||||
m_strides,
|
||||
m_dilations,
|
||||
m_auto_pad,
|
||||
m_output_padding,
|
||||
m_pads_begin,
|
||||
m_pads_end);
|
||||
}
|
||||
const PartialShape data_spatial_shape = [data_pshape]() {
|
||||
vector<Dimension> data_dims{data_pshape};
|
||||
data_dims.erase(data_dims.begin(), data_dims.begin() + 2); // remove {N, C_IN}
|
||||
return PartialShape{data_dims};
|
||||
}();
|
||||
|
||||
// C_OUTPUT
|
||||
output_shape.insert(output_shape.begin(), filters_shape.at(1));
|
||||
const PartialShape filters_spatial_shape = [filters_pshape]() {
|
||||
vector<Dimension> filters_dims{filters_pshape};
|
||||
filters_dims.erase(filters_dims.begin(),
|
||||
filters_dims.begin() + 2); // remove {C_IN, C_OUT}
|
||||
return PartialShape{filters_dims};
|
||||
}();
|
||||
|
||||
// If auto_pad has one of following mode we infer paddings. Otherwise in
|
||||
// EXPLICIT auto_pad mode we use what is provided.
|
||||
if ((m_auto_pad == PadType::SAME_UPPER || m_auto_pad == PadType::SAME_LOWER) &&
|
||||
(data_spatial_shape.is_static() && filters_spatial_shape.is_static() &&
|
||||
output_spatial_pshape.is_static()))
|
||||
{
|
||||
opset1::infer_conv_backprop_auto_padding(data_spatial_shape.to_shape(),
|
||||
filters_spatial_shape.to_shape(),
|
||||
output_spatial_pshape.to_shape(),
|
||||
m_strides,
|
||||
m_dilations,
|
||||
m_auto_pad,
|
||||
m_output_padding,
|
||||
m_pads_begin,
|
||||
m_pads_end);
|
||||
}
|
||||
}
|
||||
vector<Dimension> output_pshape{output_spatial_pshape};
|
||||
// C_OUT
|
||||
auto n_out_channels =
|
||||
filters_pshape.rank().is_static() ? filters_pshape[1] : Dimension::dynamic();
|
||||
output_pshape.insert(output_pshape.begin(), n_out_channels);
|
||||
// N
|
||||
output_shape.insert(output_shape.begin(), data_shape.at(0));
|
||||
output_pshape = output_shape;
|
||||
auto batches = data_pshape.rank().is_static() ? data_pshape[0] : Dimension::dynamic();
|
||||
output_pshape.insert(output_pshape.begin(), batches);
|
||||
result_pshape = PartialShape{output_pshape};
|
||||
}
|
||||
set_input_is_relevant_to_shape(2);
|
||||
}
|
||||
@@ -337,35 +413,50 @@ void op::v1::ConvolutionBackpropData::validate_and_infer_types()
|
||||
m_pads_end.assign(m_pads_end.size(), 0);
|
||||
}
|
||||
|
||||
if (data_pshape.rank().is_static() && filters_pshape.is_static())
|
||||
vector<Dimension> output_pshape;
|
||||
if (data_pshape.rank().is_static() && filters_pshape.rank().is_static())
|
||||
{
|
||||
vector<Dimension> data_shape{data_pshape}, filters_shape{filters_pshape}, output_shape;
|
||||
auto data_spatial_shape = [data_pshape]() {
|
||||
vector<Dimension> data_dims{data_pshape};
|
||||
return vector<Dimension>{std::next(data_dims.begin(), 2),
|
||||
std::end(data_dims)}; // remove {N, C_IN}
|
||||
}();
|
||||
|
||||
infer_conv_backprop_output_spatial_shape(
|
||||
vector<Dimension>{std::next(data_shape.begin(), 2), std::end(data_shape)},
|
||||
vector<Dimension>{std::next(filters_shape.begin(), 2), std::end(filters_shape)},
|
||||
m_strides,
|
||||
m_dilations,
|
||||
m_pads_begin,
|
||||
m_pads_end,
|
||||
m_output_padding,
|
||||
output_shape);
|
||||
auto filters_spatial_shape = [filters_pshape]() {
|
||||
vector<Dimension> filters_dims{filters_pshape};
|
||||
return vector<Dimension>{std::next(filters_dims.begin(), 2), // remove {C_IN, C_OUT}
|
||||
std::end(filters_dims)};
|
||||
}();
|
||||
|
||||
// C_OUTPUT
|
||||
output_shape.insert(output_shape.begin(), filters_shape.at(1));
|
||||
// N
|
||||
output_shape.insert(output_shape.begin(), data_shape.at(0));
|
||||
output_pshape = PartialShape{output_shape};
|
||||
infer_conv_backprop_output_spatial_shape(data_spatial_shape,
|
||||
filters_spatial_shape,
|
||||
m_strides,
|
||||
m_dilations,
|
||||
m_pads_begin,
|
||||
m_pads_end,
|
||||
m_output_padding,
|
||||
output_pshape);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_pshape = PartialShape::dynamic(data_pshape.rank());
|
||||
output_pshape = vector<Dimension>{output_spatial_pshape};
|
||||
}
|
||||
|
||||
if (output_pshape.size())
|
||||
{
|
||||
// C_OUT
|
||||
auto n_out_channels =
|
||||
filters_pshape.rank().is_static() ? filters_pshape[1] : Dimension::dynamic();
|
||||
output_pshape.insert(output_pshape.begin(), n_out_channels);
|
||||
// N
|
||||
auto batches = data_pshape.rank().is_static() ? data_pshape[0] : Dimension::dynamic();
|
||||
output_pshape.insert(output_pshape.begin(), batches);
|
||||
result_pshape = PartialShape{output_pshape};
|
||||
}
|
||||
}
|
||||
|
||||
set_input_is_relevant_to_shape(0);
|
||||
set_input_is_relevant_to_shape(1);
|
||||
set_output_type(0, result_et, output_pshape);
|
||||
set_output_type(0, result_et, result_pshape);
|
||||
}
|
||||
|
||||
shared_ptr<Node>
|
||||
|
||||
+8
-7
@@ -2,16 +2,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ngraph_ops/type_relaxed.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace op {
|
||||
namespace ngraph
|
||||
{
|
||||
namespace op
|
||||
{
|
||||
TypeRelaxedBase::~TypeRelaxedBase() {}
|
||||
|
||||
TypeRelaxedBase::~TypeRelaxedBase() {}
|
||||
|
||||
} // namespace op
|
||||
} // namespace ngraph
|
||||
} // namespace op
|
||||
} // namespace ngraph
|
||||
@@ -4,64 +4,18 @@
|
||||
|
||||
#include "ngraph/pass/convert_fp32_to_fp16.hpp"
|
||||
#include "ngraph/graph_util.hpp"
|
||||
#include "ngraph/op/constant.hpp"
|
||||
#include "ngraph/pass/manager.hpp"
|
||||
#include "transformations/convert_precision.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertFP32ToFP16, "ConvertFP32ToFP16", 0);
|
||||
|
||||
void pass::ConvertFP32ToFP16::convert_constants_precision()
|
||||
bool ngraph::pass::ConvertFP32ToFP16::run_on_function(std::shared_ptr<ngraph::Function> f)
|
||||
{
|
||||
auto constant =
|
||||
std::make_shared<ngraph::op::Constant>(element::f32, Shape{1}, std::vector<float>{0});
|
||||
|
||||
ngraph::graph_rewrite_callback callback = [](pattern::Matcher& m) {
|
||||
auto constant = std::dynamic_pointer_cast<ngraph::op::Constant>(m.get_match_root());
|
||||
if (!constant)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (constant->get_element_type() == element::f32)
|
||||
{
|
||||
auto data = constant->get_vector<float>();
|
||||
std::vector<ngraph::float16> new_data(data.size());
|
||||
for (size_t i = 0; i < data.size(); ++i)
|
||||
{
|
||||
new_data[i] = ngraph::float16(data[i]);
|
||||
}
|
||||
auto new_const = std::make_shared<ngraph::op::Constant>(
|
||||
element::f16, constant->get_shape(), new_data);
|
||||
new_const->set_friendly_name(constant->get_friendly_name());
|
||||
ngraph::replace_node(constant, new_const);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto m = std::make_shared<ngraph::pattern::Matcher>(constant, "ConvertFP32ToFP16");
|
||||
NGRAPH_SUPPRESS_DEPRECATED_START
|
||||
this->add_matcher(m, callback, PassProperty::CHANGE_DYNAMIC_STATE);
|
||||
NGRAPH_SUPPRESS_DEPRECATED_END
|
||||
}
|
||||
|
||||
void pass::ConvertFP32ToFP16::convert_parameters_precision()
|
||||
{
|
||||
auto constant = std::make_shared<ngraph::op::Parameter>(element::f32, Shape{1});
|
||||
|
||||
ngraph::graph_rewrite_callback callback = [](pattern::Matcher& m) {
|
||||
auto parameter = std::dynamic_pointer_cast<ngraph::op::Parameter>(m.get_match_root());
|
||||
if (parameter && parameter->get_element_type() == element::f32)
|
||||
{
|
||||
parameter->set_element_type(element::f16);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto m = std::make_shared<ngraph::pattern::Matcher>(constant, "ConvertFP32ToFP16");
|
||||
NGRAPH_SUPPRESS_DEPRECATED_START
|
||||
this->add_matcher(m, callback, PassProperty::CHANGE_DYNAMIC_STATE);
|
||||
NGRAPH_SUPPRESS_DEPRECATED_END
|
||||
ngraph::pass::Manager m(get_pass_config());
|
||||
m.register_pass<ngraph::pass::ConvertPrecision>(ngraph::element::f32, ngraph::element::f16);
|
||||
m.run_passes(f);
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,830 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "transformations/convert_precision.hpp"
|
||||
#include "itt.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <ngraph/opsets/opset1.hpp>
|
||||
#include <ngraph/opsets/opset3.hpp>
|
||||
#include <ngraph/opsets/opset4.hpp>
|
||||
#include <ngraph/opsets/opset5.hpp>
|
||||
#include <ngraph/opsets/opset6.hpp>
|
||||
#include "ngraph_ops/type_relaxed.hpp"
|
||||
|
||||
#include <ngraph/runtime/reference/convert.hpp>
|
||||
|
||||
using namespace ngraph;
|
||||
|
||||
bool fuse_type_to_constant(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
const std::vector<ngraph::Input<ngraph::Node>>& consumers);
|
||||
bool fuse_type_to_shapeof(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_shapeof_v0(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_parameter(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_convert(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_nms3(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_nms4(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_nms5(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_topk(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_nonzero(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_bucketize(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
bool fuse_type_to_ctc_greedy_decoder_seq_len(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
|
||||
bool extend_select_type(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx);
|
||||
|
||||
template <typename T>
|
||||
bool fuse_type_to_binary_comparision(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node))
|
||||
{
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
return true;
|
||||
}
|
||||
else if (auto casted = std::dynamic_pointer_cast<T>(node))
|
||||
{
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<T>>(
|
||||
*casted, element::TypeVector{}, element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool fuse_type_to_logical(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node))
|
||||
{
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
type_relaxed->set_origin_input_type(element::boolean, 0);
|
||||
type_relaxed->set_origin_input_type(element::boolean, 1);
|
||||
return true;
|
||||
}
|
||||
else if (auto casted = std::dynamic_pointer_cast<T>(node))
|
||||
{
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<T>>(
|
||||
*casted,
|
||||
element::TypeVector{element::boolean, element::boolean},
|
||||
element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool fuse_type_to_reduce_logical(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node))
|
||||
{
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
type_relaxed->set_origin_input_type(element::boolean, 0);
|
||||
return true;
|
||||
}
|
||||
else if (auto casted = std::dynamic_pointer_cast<T>(node))
|
||||
{
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<T>>(
|
||||
*casted, element::TypeVector{element::boolean}, element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertPrecision, "ConvertPrecision", 0);
|
||||
|
||||
bool ngraph::pass::ConvertPrecision::run_on_function(std::shared_ptr<ngraph::Function> f)
|
||||
{
|
||||
type_to_fuse_map type_to_fuse{
|
||||
{opset4::Parameter::type_info, fuse_type_to_parameter},
|
||||
{opset4::Convert::type_info, fuse_type_to_convert},
|
||||
{opset4::ShapeOf::type_info, fuse_type_to_shapeof},
|
||||
{opset3::NonMaxSuppression::type_info, fuse_type_to_nms3},
|
||||
{opset4::NonMaxSuppression::type_info, fuse_type_to_nms4},
|
||||
{opset5::NonMaxSuppression::type_info, fuse_type_to_nms5},
|
||||
{opset6::CTCGreedyDecoderSeqLen::type_info, fuse_type_to_ctc_greedy_decoder_seq_len},
|
||||
{opset4::TopK::type_info, fuse_type_to_topk},
|
||||
{opset4::NonZero::type_info, fuse_type_to_nonzero},
|
||||
{opset4::Bucketize::type_info, fuse_type_to_bucketize},
|
||||
{opset4::Equal::type_info, fuse_type_to_binary_comparision<opset4::Equal>},
|
||||
{opset4::NotEqual::type_info, fuse_type_to_binary_comparision<opset4::NotEqual>},
|
||||
{opset4::Greater::type_info, fuse_type_to_binary_comparision<opset4::Greater>},
|
||||
{opset4::GreaterEqual::type_info, fuse_type_to_binary_comparision<opset4::GreaterEqual>},
|
||||
{opset4::Less::type_info, fuse_type_to_binary_comparision<opset4::Less>},
|
||||
{opset4::LessEqual::type_info, fuse_type_to_binary_comparision<opset4::LessEqual>},
|
||||
{opset4::LogicalAnd::type_info, fuse_type_to_logical<opset4::LogicalAnd>},
|
||||
{opset4::LogicalOr::type_info, fuse_type_to_logical<opset4::LogicalOr>},
|
||||
{opset4::LogicalXor::type_info, fuse_type_to_logical<opset4::LogicalXor>},
|
||||
{opset4::LogicalNot::type_info, fuse_type_to_logical<opset4::LogicalNot>},
|
||||
{opset4::ReduceLogicalAnd::type_info,
|
||||
fuse_type_to_reduce_logical<opset4::ReduceLogicalAnd>},
|
||||
{opset4::ReduceLogicalOr::type_info, fuse_type_to_reduce_logical<opset4::ReduceLogicalOr>},
|
||||
{opset1::ShapeOf::type_info, fuse_type_to_shapeof_v0}};
|
||||
|
||||
type_to_fuse.insert(m_additional_type_to_fuse_map.begin(), m_additional_type_to_fuse_map.end());
|
||||
|
||||
static type_to_fuse_map type_to_extend{
|
||||
{opset4::Select::type_info, extend_select_type},
|
||||
};
|
||||
|
||||
// As Constant operations can be shared between multiple nGraph Functions so before
|
||||
// changing precision we need to understand which Constant consumers belongs
|
||||
// to the current nGraph Function
|
||||
std::map<const std::shared_ptr<ngraph::Node>, std::vector<Input<Node>>>
|
||||
const_to_internal_output;
|
||||
|
||||
std::function<void(const std::shared_ptr<Function>&)> register_constants =
|
||||
[&const_to_internal_output](const std::shared_ptr<Function>& f) {
|
||||
for (auto& node : f->get_ordered_ops())
|
||||
{
|
||||
for (auto& input : node->inputs())
|
||||
{
|
||||
if (auto const_node = std::dynamic_pointer_cast<opset4::Constant>(
|
||||
input.get_source_output().get_node_shared_ptr()))
|
||||
{
|
||||
const_to_internal_output[const_node].emplace_back(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto convert_node_output_precision = [this, &const_to_internal_output, &type_to_fuse](
|
||||
const std::shared_ptr<ngraph::Node>& node) {
|
||||
for (auto output : node->outputs())
|
||||
{
|
||||
if (output.get_element_type() == m_from)
|
||||
{
|
||||
// Handle case with Constants as they can have consumers from other nGraph Function
|
||||
// object
|
||||
if (ngraph::op::is_constant(node) && const_to_internal_output.count(node))
|
||||
{
|
||||
fuse_type_to_constant(node, m_to, const_to_internal_output.at(node));
|
||||
break;
|
||||
}
|
||||
|
||||
// Check that node type exists in map and we can fuse type into node
|
||||
if (type_to_fuse.count(node->get_type_info()) &&
|
||||
type_to_fuse.at(node->get_type_info())(node, m_to, output.get_index()))
|
||||
{
|
||||
// We need to break if original node was replaced
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto convert_node_input_precision = [this](const std::shared_ptr<ngraph::Node>& node) {
|
||||
for (auto input : node->inputs())
|
||||
{
|
||||
if (input.get_element_type() == m_from)
|
||||
{
|
||||
// For some operations we need to extend their input types to support new type
|
||||
if (type_to_extend.count(node->get_type_info()) &&
|
||||
type_to_extend.at(node->get_type_info())(node, m_to, input.get_index()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::function<void(const std::shared_ptr<Function>&)> convert_function_precision =
|
||||
[this,
|
||||
®ister_constants,
|
||||
&convert_node_output_precision,
|
||||
&convert_node_input_precision,
|
||||
&convert_function_precision](const std::shared_ptr<Function>& f) {
|
||||
// Iterate over all nodes in topological order and then iterate over node outputs.
|
||||
// If output type mismatch given type we try to fuse type into this operation
|
||||
// otherwise we insert Convert operation.
|
||||
for (auto& node : f->get_ordered_ops())
|
||||
{
|
||||
transformation_callback(node);
|
||||
// Recursively apply transformation for sub-graph based operations
|
||||
if (auto sub_graph_node = std::dynamic_pointer_cast<op::util::SubGraphOp>(node))
|
||||
{
|
||||
if (auto sub_graph = sub_graph_node->get_function())
|
||||
{
|
||||
convert_function_precision(sub_graph);
|
||||
}
|
||||
}
|
||||
convert_node_input_precision(node);
|
||||
}
|
||||
// Register internal constants only after fixing input type that could lead to nodes
|
||||
// replacement
|
||||
register_constants(f);
|
||||
|
||||
for (auto& node : f->get_ordered_ops())
|
||||
{
|
||||
convert_node_output_precision(node);
|
||||
}
|
||||
};
|
||||
|
||||
convert_function_precision(f);
|
||||
f->validate_nodes_and_infer_types();
|
||||
|
||||
// TODO: we need to split NopElimination pass to separate MatcherPasses and call Convert
|
||||
// elimination here
|
||||
for (auto& node : f->get_ordered_ops())
|
||||
{
|
||||
if (auto convert = std::dynamic_pointer_cast<opset4::Convert>(node))
|
||||
{
|
||||
// WA for topK, dont remove fake convert
|
||||
if (convert->input(0).get_element_type() == convert->get_convert_element_type() &&
|
||||
convert->input_value(0).get_node_shared_ptr()->get_output_size() == 1)
|
||||
{
|
||||
replace_output_update_name(convert->output(0), convert->input_value(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fuse_type_to_shapeof(const std::shared_ptr<ngraph::Node>& node, element::Type to, size_t idx)
|
||||
{
|
||||
if (auto shapeof = as_type_ptr<opset4::ShapeOf>(node))
|
||||
{
|
||||
if (to == element::i32 || to == element::i64)
|
||||
{
|
||||
shapeof->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_parameter(const std::shared_ptr<ngraph::Node>& node, element::Type to, size_t idx)
|
||||
{
|
||||
if (auto param = as_type_ptr<opset4::Parameter>(node))
|
||||
{
|
||||
param->set_element_type(to);
|
||||
param->validate_and_infer_types();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_convert(const std::shared_ptr<ngraph::Node>& node, element::Type to, size_t idx)
|
||||
{
|
||||
if (auto convert = as_type_ptr<opset4::Convert>(node))
|
||||
{
|
||||
convert->set_convert_element_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nms3(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto nms = as_type_ptr<opset3::NonMaxSuppression>(node))
|
||||
{
|
||||
nms->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nms4(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto nms = as_type_ptr<opset4::NonMaxSuppression>(node))
|
||||
{
|
||||
nms->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nms5(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto nms = as_type_ptr<opset5::NonMaxSuppression>(node))
|
||||
{
|
||||
nms->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_topk(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto topk = as_type_ptr<opset4::TopK>(node))
|
||||
{
|
||||
if (idx == 1 && (to == element::i32 || to == element::i64))
|
||||
{
|
||||
topk->set_index_element_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_ctc_greedy_decoder_seq_len(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto ctc_decoder = as_type_ptr<opset6::CTCGreedyDecoderSeqLen>(node))
|
||||
{
|
||||
if (idx == 0 && (to == element::i32 || to == element::i64))
|
||||
{
|
||||
ctc_decoder->set_classes_index_type(to);
|
||||
return true;
|
||||
}
|
||||
if (idx == 1 && (to == element::i32 || to == element::i64))
|
||||
{
|
||||
ctc_decoder->set_sequence_length_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_nonzero(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto nonzero = as_type_ptr<opset4::NonZero>(node))
|
||||
{
|
||||
if (to == element::i32 || to == element::i64)
|
||||
{
|
||||
nonzero->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_bucketize(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto b = as_type_ptr<opset4::Bucketize>(node))
|
||||
{
|
||||
if (to == element::i32 || to == element::i64)
|
||||
{
|
||||
b->set_output_type(to);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fuse_type_to_shapeof_v0(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node))
|
||||
{
|
||||
type_relaxed->set_overridden_output_type(to);
|
||||
return true;
|
||||
}
|
||||
else if (auto casted = std::dynamic_pointer_cast<opset1::ShapeOf>(node))
|
||||
{
|
||||
auto relaxed_op = std::make_shared<ngraph::op::TypeRelaxed<opset1::ShapeOf>>(
|
||||
*casted, element::TypeVector{}, element::TypeVector{to});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool extend_select_type(const std::shared_ptr<ngraph::Node>& node,
|
||||
ngraph::element::Type to,
|
||||
size_t idx)
|
||||
{
|
||||
if (auto type_relaxed = std::dynamic_pointer_cast<op::TypeRelaxedBase>(node))
|
||||
{
|
||||
type_relaxed->set_origin_input_type(element::boolean, 0);
|
||||
return true;
|
||||
}
|
||||
else if (auto casted = std::dynamic_pointer_cast<opset4::Select>(node))
|
||||
{
|
||||
auto relaxed_op = std::make_shared<op::TypeRelaxed<opset4::Select>>(
|
||||
*casted, element::TypeVector{element::boolean}, element::TypeVector{});
|
||||
replace_node(node, relaxed_op);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename src_type, typename dst_type>
|
||||
inline dst_type convert_value(src_type val)
|
||||
{
|
||||
if (val > std::numeric_limits<dst_type>::max())
|
||||
{
|
||||
return std::numeric_limits<dst_type>::max();
|
||||
}
|
||||
else if (val < std::numeric_limits<dst_type>::lowest())
|
||||
{
|
||||
return std::numeric_limits<dst_type>::lowest();
|
||||
}
|
||||
return static_cast<dst_type>(val);
|
||||
}
|
||||
|
||||
// We need to treat U64->I32 and U32->I32 as a separate case, because of C++'s implicit promotion
|
||||
// from signed to unsigned, and we don't need to compare and clamp the input to
|
||||
// std::numeric_limits<int32_t>::lowest()
|
||||
template <>
|
||||
inline int32_t convert_value<uint64_t, int32_t>(uint64_t val)
|
||||
{
|
||||
if (val > static_cast<uint64_t>(std::numeric_limits<int32_t>::max()))
|
||||
{
|
||||
return std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
return static_cast<int32_t>(val);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int32_t convert_value<uint32_t, int32_t>(uint32_t val)
|
||||
{
|
||||
if (val > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))
|
||||
{
|
||||
return std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
return static_cast<int32_t>(val);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <element::Type_t PREC_FROM, element::Type_t PREC_TO>
|
||||
std::shared_ptr<ngraph::Node>
|
||||
change_constant_precision(std::shared_ptr<opset4::Constant>& constant)
|
||||
{
|
||||
using src_type = typename element_type_traits<PREC_FROM>::value_type;
|
||||
using dst_type = typename element_type_traits<PREC_TO>::value_type;
|
||||
|
||||
const auto* src_data = constant->get_data_ptr<src_type>();
|
||||
const auto size = shape_size(constant->get_shape());
|
||||
|
||||
auto new_constant =
|
||||
std::make_shared<ngraph::opset4::Constant>(PREC_TO, constant->get_shape());
|
||||
auto* dst_data =
|
||||
const_cast<dst_type*>(reinterpret_cast<const dst_type*>(new_constant->get_data_ptr()));
|
||||
if (dst_data == nullptr)
|
||||
throw ngraph_error("Can't get destination data pointer");
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
dst_data[i] = convert_value<src_type, dst_type>(src_data[i]);
|
||||
}
|
||||
return new_constant;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::shared_ptr<Node> change_constant_precision<element::Type_t::f16, element::Type_t::f32>(
|
||||
std::shared_ptr<opset4::Constant>& constant)
|
||||
{
|
||||
using src_type = typename element_type_traits<element::Type_t::f16>::value_type;
|
||||
using dst_type = typename element_type_traits<element::Type_t::f32>::value_type;
|
||||
|
||||
const auto* src_data = constant->get_data_ptr<src_type>();
|
||||
const auto size = shape_size(constant->get_shape());
|
||||
|
||||
auto new_constant =
|
||||
std::make_shared<ngraph::opset4::Constant>(element::Type_t::f32, constant->get_shape());
|
||||
auto* dst_data =
|
||||
const_cast<dst_type*>(reinterpret_cast<const dst_type*>(new_constant->get_data_ptr()));
|
||||
if (dst_data == nullptr)
|
||||
throw ngraph_error("Can't get destination data pointer");
|
||||
|
||||
ngraph::runtime::reference::convert<src_type, dst_type>(src_data, dst_data, size);
|
||||
|
||||
return new_constant;
|
||||
}
|
||||
|
||||
struct EnumClassHash
|
||||
{
|
||||
template <class T>
|
||||
std::size_t operator()(T t) const
|
||||
{
|
||||
return static_cast<size_t>(t);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Method converts low precision integer types
|
||||
* The method uses the next logic for conversion:
|
||||
* * For unsigned types we just copy all bits to destination type (which is bigger):
|
||||
* int4 [1011] -> int8 [00001011]
|
||||
* * For signed types we copy all bits (except sign bit) to destination type and after
|
||||
* that for negative values we set to 1 all higher bits:
|
||||
* int4 [1011] -> int8 [11111011]
|
||||
*
|
||||
* @param src source value !!! the type must be unsigned !!!
|
||||
* @param dst destination value !!! the type must be unsigned !!!
|
||||
* @param src_offset source offset (for custom data types)
|
||||
* @param src_size source size (for custom data types)
|
||||
* @param dst_offset destination offset
|
||||
* @param dst_size destination size
|
||||
* @param is_signed the type of source data
|
||||
*/
|
||||
template <class SRC, class DST>
|
||||
void convert_lp_value(const SRC& src,
|
||||
DST& dst,
|
||||
size_t src_offset,
|
||||
size_t src_size,
|
||||
size_t dst_offset,
|
||||
size_t dst_size,
|
||||
bool is_signed)
|
||||
{
|
||||
constexpr SRC src_max = std::numeric_limits<SRC>::max();
|
||||
constexpr DST dst_max = std::numeric_limits<DST>::max();
|
||||
// Make a shift for the source value
|
||||
// src [11101000] offset 2, size 4
|
||||
// val [00011101]
|
||||
SRC val = src >> src_offset;
|
||||
// dst [10001111 00000100] offset 5 size 9
|
||||
// new_val [00000000 00000000]
|
||||
DST new_val = 0;
|
||||
|
||||
// Calculate diff in order to clean bits which don't exist in the source value
|
||||
// diff 4
|
||||
size_t diff = sizeof(SRC) * 8 - src_size;
|
||||
// Clean unnecessary bits
|
||||
// val [11010000]
|
||||
val = val << diff;
|
||||
// val [00001101]
|
||||
val = val >> diff;
|
||||
|
||||
// Get the sign of value
|
||||
// sign [00000001]
|
||||
SRC sign = (val >> (src_size - 1)) & 0b1;
|
||||
|
||||
// If source type is signed and negative
|
||||
if (is_signed && sign)
|
||||
{
|
||||
// val [11111101]
|
||||
val |= src_max << diff;
|
||||
// new_val [00000001 11111111]
|
||||
new_val = dst_max >> (sizeof(DST) * 8 - dst_size);
|
||||
// new_val [00000001 11111101]
|
||||
new_val &= (dst_max << sizeof(SRC) * 8) | val;
|
||||
}
|
||||
else
|
||||
{
|
||||
// new_val [00000000 00001101]
|
||||
new_val = val;
|
||||
}
|
||||
|
||||
// Make a mask in order to save other values if DST contains several values
|
||||
// mask [11000000 00011111]
|
||||
DST mask = 0;
|
||||
if (dst_offset + dst_size < sizeof(DST) * 8)
|
||||
mask = (dst_max << (dst_offset + dst_size));
|
||||
if (dst_offset != 0)
|
||||
mask |= (dst_max >> (sizeof(DST) * 8 - dst_offset));
|
||||
|
||||
// Add mask to our converted value
|
||||
// signed: new_val [11100000 10111111]
|
||||
// unsigned: new_val [11000001 10111111]
|
||||
new_val = mask | (new_val << dst_offset);
|
||||
|
||||
// Add our value to destination
|
||||
// dst: [10111111 11100100]
|
||||
dst |= ~mask;
|
||||
// signed: dst [10100000 10100100]
|
||||
// unsigned: dst [10000001 10100100]
|
||||
dst &= new_val;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> convert_low_precisions_int(std::shared_ptr<opset4::Constant>& constant,
|
||||
element::Type to)
|
||||
{
|
||||
// Supported integer precisions
|
||||
static const std::unordered_set<element::Type_t, EnumClassHash>
|
||||
supported_integer_precisions = {element::i4, element::u4, element::u1};
|
||||
// Get source element type and source data
|
||||
auto src_type = constant->get_element_type();
|
||||
const auto* src_data = reinterpret_cast<const uint8_t*>(constant->get_data_ptr());
|
||||
|
||||
// We support conversion only if several elements can be represented in one instance of some
|
||||
// C++ common data type without any exception, destination data type should be bigger than
|
||||
// source and destination data type should be real
|
||||
if (!supported_integer_precisions.count(src_type) ||
|
||||
(src_type.size() * 8) % src_type.bitwidth() || (to.size() * 8) % to.bitwidth() ||
|
||||
to.is_real() || to.bitwidth() < src_type.bitwidth())
|
||||
throw ngraph_error("Convert low precision for " +
|
||||
constant->get_element_type().get_type_name() + " to " +
|
||||
to.get_type_name() + " is not implemented!");
|
||||
|
||||
// Create a new constant operation and get destination data
|
||||
auto new_constant = std::make_shared<ngraph::opset4::Constant>(to, constant->get_shape());
|
||||
auto* dst_data =
|
||||
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(new_constant->get_data_ptr()));
|
||||
// Check pointers
|
||||
if (src_data == nullptr || dst_data == nullptr)
|
||||
throw ngraph_error("Can't get data pointer");
|
||||
|
||||
// Convert values
|
||||
const auto size = shape_size(constant->get_shape());
|
||||
size_t src_idx(0), dst_idx(0), dst_off(0), src_off(0);
|
||||
if (src_type.bitwidth() < 8)
|
||||
{
|
||||
src_off = 8 - src_type.bitwidth();
|
||||
}
|
||||
|
||||
if (to.bitwidth() < 8)
|
||||
{
|
||||
dst_off = 8 - to.bitwidth();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
// Source type at the current moment always less than 1 byte
|
||||
// Select the right destination type
|
||||
switch (to.size())
|
||||
{
|
||||
case 1:
|
||||
convert_lp_value<uint8_t, uint8_t>(src_data[src_idx],
|
||||
dst_data[dst_idx],
|
||||
src_off,
|
||||
src_type.bitwidth(),
|
||||
dst_off,
|
||||
to.bitwidth(),
|
||||
src_type.is_signed());
|
||||
break;
|
||||
case 2:
|
||||
convert_lp_value<uint8_t, uint16_t>(src_data[src_idx],
|
||||
reinterpret_cast<uint16_t*>(dst_data)[dst_idx],
|
||||
src_off,
|
||||
src_type.bitwidth(),
|
||||
dst_off,
|
||||
to.bitwidth(),
|
||||
src_type.is_signed());
|
||||
break;
|
||||
case 4:
|
||||
convert_lp_value<uint8_t, uint32_t>(src_data[src_idx],
|
||||
reinterpret_cast<uint32_t*>(dst_data)[dst_idx],
|
||||
src_off,
|
||||
src_type.bitwidth(),
|
||||
dst_off,
|
||||
to.bitwidth(),
|
||||
src_type.is_signed());
|
||||
break;
|
||||
case 8:
|
||||
convert_lp_value<uint8_t, uint64_t>(src_data[src_idx],
|
||||
reinterpret_cast<uint64_t*>(dst_data)[dst_idx],
|
||||
src_off,
|
||||
src_type.bitwidth(),
|
||||
dst_off,
|
||||
to.bitwidth(),
|
||||
src_type.is_signed());
|
||||
break;
|
||||
default: throw ngraph_error("Unsupported element size!");
|
||||
}
|
||||
// Calculate offsets and indexes
|
||||
if (src_type.bitwidth() < 8)
|
||||
{
|
||||
if (src_off == 0)
|
||||
{
|
||||
src_off = 8;
|
||||
src_idx++;
|
||||
}
|
||||
src_off -= src_type.bitwidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
src_idx++;
|
||||
}
|
||||
if (to.bitwidth() < 8)
|
||||
{
|
||||
if (dst_off == 0)
|
||||
{
|
||||
dst_off = 8;
|
||||
dst_idx++;
|
||||
}
|
||||
dst_off -= to.bitwidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
return new_constant;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool fuse_type_to_constant(const std::shared_ptr<ngraph::Node>& node,
|
||||
element::Type to,
|
||||
const std::vector<Input<Node>>& consumers)
|
||||
{
|
||||
if (auto constant = as_type_ptr<opset4::Constant>(node))
|
||||
{
|
||||
auto from = constant->get_element_type();
|
||||
std::shared_ptr<ngraph::Node> new_const;
|
||||
if (from == element::u64 && to == element::i32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::u64, element::Type_t::i32>(constant);
|
||||
}
|
||||
else if (from == element::i64 && to == element::i32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::i64, element::Type_t::i32>(constant);
|
||||
}
|
||||
else if (from == element::u8 && to == element::i32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::u8, element::Type_t::i32>(constant);
|
||||
}
|
||||
else if (from == element::u16 && to == element::i32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::u16, element::Type_t::i32>(constant);
|
||||
}
|
||||
else if (from == element::i16 && to == element::i32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::i16, element::Type_t::i32>(constant);
|
||||
}
|
||||
else if (from == element::u32 && to == element::i32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::u32, element::Type_t::i32>(constant);
|
||||
}
|
||||
else if (from == element::f64 && to == element::f32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::f64, element::Type_t::f32>(constant);
|
||||
}
|
||||
else if (from == element::f32 && to == element::f16)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::f32, element::Type_t::f16>(constant);
|
||||
}
|
||||
else if (from == element::f16 && to == element::f32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::f16, element::Type_t::f32>(constant);
|
||||
}
|
||||
else if (from == element::boolean && to == element::u8)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::boolean, element::Type_t::u8>(constant);
|
||||
}
|
||||
else if (from == element::boolean && to == element::i32)
|
||||
{
|
||||
new_const =
|
||||
change_constant_precision<element::Type_t::boolean, element::Type_t::i32>(constant);
|
||||
}
|
||||
else if (from == element::i4 || from == element::u4 || from == element::u1)
|
||||
{
|
||||
new_const = convert_low_precisions_int(constant, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ngraph_error("Precision conversion from " + from.get_type_name() + " to " +
|
||||
to.get_type_name() + " is not supported");
|
||||
}
|
||||
for (auto& output : consumers)
|
||||
{
|
||||
output.replace_source_output(new_const);
|
||||
}
|
||||
|
||||
new_const->validate_and_infer_types();
|
||||
new_const->set_friendly_name(constant->get_friendly_name());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -38,14 +38,10 @@ namespace ngraph
|
||||
{
|
||||
OutputVector squeeze(const Node& node)
|
||||
{
|
||||
auto inputs = node.get_ng_inputs();
|
||||
const auto inputs = node.get_ng_inputs();
|
||||
if (inputs.size() < 2)
|
||||
{
|
||||
std::vector<int64_t> axes{};
|
||||
auto axes_node = std::make_shared<default_opset::Constant>(
|
||||
element::Type_t::u64, Shape{}, axes);
|
||||
|
||||
return {std::make_shared<default_opset::Squeeze>(inputs.at(0), axes_node)};
|
||||
return {std::make_shared<default_opset::Squeeze>(inputs.at(0))};
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -56,8 +56,6 @@ xfail_issue_35912 = xfail_test(reason="RuntimeError: Error of validate layer: B
|
||||
xfail_issue_35923 = xfail_test(reason="RuntimeError: PReLU without weights is not supported")
|
||||
xfail_issue_35925 = xfail_test(reason="Assertion error - reduction ops results mismatch")
|
||||
xfail_issue_35927 = xfail_test(reason="RuntimeError: B has zero dimension that is not allowable")
|
||||
xfail_issue_35930 = xfail_test(reason="onnx.onnx_cpp2py_export.checker.ValidationError: "
|
||||
"Required attribute 'to' is missing.")
|
||||
xfail_issue_36480 = xfail_test(reason="RuntimeError: [NOT_FOUND] Unsupported property dummy_option "
|
||||
"by CPU plugin")
|
||||
xfail_issue_36485 = xfail_test(reason="RuntimeError: Check 'm_group >= 1' failed at "
|
||||
|
||||
@@ -10,7 +10,6 @@ from onnx.helper import make_graph, make_model, make_node, make_tensor_value_inf
|
||||
from ngraph.exceptions import NgraphTypeError
|
||||
from tests.runtime import get_runtime
|
||||
from tests.test_onnx.utils import get_node_model, import_onnx_model, run_model, run_node
|
||||
from tests import xfail_issue_35930
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -378,8 +377,9 @@ def test_cast_to_uint(val_type):
|
||||
assert np.allclose(result, expected)
|
||||
|
||||
|
||||
@xfail_issue_35930
|
||||
def test_cast_errors():
|
||||
from onnx.onnx_cpp2py_export.checker import ValidationError
|
||||
|
||||
np.random.seed(133391)
|
||||
input_data = np.ceil(np.random.rand(2, 3, 4) * 16)
|
||||
|
||||
@@ -396,7 +396,7 @@ def test_cast_errors():
|
||||
|
||||
graph = make_graph([node], "compute_graph", input_tensors, output_tensors)
|
||||
model = make_model(graph, producer_name="NgraphBackend")
|
||||
with pytest.raises(RuntimeError):
|
||||
with pytest.raises(ValidationError):
|
||||
import_onnx_model(model)
|
||||
|
||||
# unsupported data type representation
|
||||
@@ -412,7 +412,7 @@ def test_cast_errors():
|
||||
|
||||
graph = make_graph([node], "compute_graph", input_tensors, output_tensors)
|
||||
model = make_model(graph, producer_name="NgraphBackend")
|
||||
with pytest.raises(RuntimeError):
|
||||
with pytest.raises(ValidationError):
|
||||
import_onnx_model(model)
|
||||
|
||||
# unsupported input tensor data type:
|
||||
|
||||
@@ -106,6 +106,7 @@ set(SRC
|
||||
type_prop/constant.cpp
|
||||
type_prop/convert.cpp
|
||||
type_prop/convolution.cpp
|
||||
type_prop/convolution_backprop_data.cpp
|
||||
type_prop/ctc_greedy_decoder.cpp
|
||||
type_prop/ctc_greedy_decoder_seq_len.cpp
|
||||
type_prop/ctc_loss.cpp
|
||||
@@ -253,8 +254,10 @@ set(SRC
|
||||
visitors/op/space_to_depth.cpp
|
||||
visitors/op/split.cpp
|
||||
visitors/op/squared_difference.cpp
|
||||
visitors/op/sqrt.cpp
|
||||
visitors/op/strided_slice.cpp
|
||||
visitors/op/topk.cpp
|
||||
visitors/op/transpose.cpp
|
||||
uint4.cpp
|
||||
util.cpp
|
||||
)
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,54 @@
|
||||
ir_version: 7
|
||||
producer_name: "nGraph ONNX Importer"
|
||||
graph {
|
||||
node {
|
||||
input: "A"
|
||||
output: "B"
|
||||
op_type: "Squeeze"
|
||||
}
|
||||
name: "compute_graph"
|
||||
input {
|
||||
name: "A"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 4
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 1
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
name: "B"
|
||||
type {
|
||||
tensor_type {
|
||||
elem_type: 1
|
||||
shape {
|
||||
dim {
|
||||
dim_value: 4
|
||||
}
|
||||
dim {
|
||||
dim_value: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opset_import {
|
||||
version: 13
|
||||
}
|
||||
@@ -372,7 +372,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_space_to_depth_no_blocksize)
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_model_squeeze)
|
||||
{
|
||||
auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/squeeze_duplicate_axes.prototxt"));
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/squeeze.prototxt"));
|
||||
|
||||
// {1, 4, 1, 1, 2}
|
||||
auto input = test::NDArray<float, 5>(
|
||||
@@ -390,6 +390,18 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_squeeze)
|
||||
test_case.run();
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_model_squeeze_opset13_no_axes)
|
||||
{
|
||||
const auto function = onnx_import::import_onnx_model(
|
||||
file_util::path_join(SERIALIZED_ZOO, "onnx/squeeze_opset13_no_axes.prototxt"));
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(function);
|
||||
const std::vector<float> data = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
|
||||
test_case.add_input<float>(Shape{1, 4, 1, 1, 2}, data);
|
||||
test_case.add_expected_output<float>(Shape{4, 2}, data);
|
||||
test_case.run();
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, onnx_model_unsqueeze)
|
||||
{
|
||||
auto function = onnx_import::import_onnx_model(
|
||||
|
||||
@@ -27,31 +27,6 @@ TEST(type_prop, conv_1d_deduce)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 100};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 10}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 91}); // output delta
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
Strides{1},
|
||||
Strides{1},
|
||||
CoordinateDiff{0},
|
||||
CoordinateDiff{0},
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{0});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_padded)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -74,35 +49,6 @@ TEST(type_prop, conv_1d_deduce_padded)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_padded)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 100};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 10}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 96}); // output delta
|
||||
auto move_strides = Strides{1};
|
||||
auto dilation_strides = Strides{1};
|
||||
auto padding_below = CoordinateDiff{2};
|
||||
auto padding_above = CoordinateDiff{3};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
dilation_strides,
|
||||
padding_below,
|
||||
padding_above,
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{2});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_strided)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -121,32 +67,6 @@ TEST(type_prop, conv_1d_deduce_strided)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_strided)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 100};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 10}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 46}); // output delta
|
||||
auto move_strides = Strides{2};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
Strides{1},
|
||||
CoordinateDiff{0},
|
||||
CoordinateDiff{0},
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{2});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{0});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_strided_padded)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -169,35 +89,6 @@ TEST(type_prop, conv_1d_deduce_strided_padded)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_strided_padded)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 100};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 10}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 48}); // output delta
|
||||
auto move_strides = Strides{2};
|
||||
auto dilation_strides = Strides{1};
|
||||
auto padding_below = CoordinateDiff{2};
|
||||
auto padding_above = CoordinateDiff{3};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
dilation_strides,
|
||||
padding_below,
|
||||
padding_above,
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{2});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{2});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_strided_small_uneven)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -216,32 +107,6 @@ TEST(type_prop, conv_1d_deduce_strided_small_uneven)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_strided_small_uneven)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 5};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 2}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 2}); // output delta
|
||||
auto move_strides = Strides{2};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
Strides{1},
|
||||
CoordinateDiff{0},
|
||||
CoordinateDiff{0},
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{2});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{0});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_strided_small_even)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -260,32 +125,6 @@ TEST(type_prop, conv_1d_deduce_strided_small_even)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_strided_small_even)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 6};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 2}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 3}); // output delta
|
||||
auto move_strides = Strides{2};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
Strides{1},
|
||||
CoordinateDiff{0},
|
||||
CoordinateDiff{0},
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{2});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{0});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_window_dilated)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -305,33 +144,6 @@ TEST(type_prop, conv_1d_deduce_window_dilated)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_window_dilated)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 100};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 10}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 82}); // output delta
|
||||
auto move_strides = Strides{1};
|
||||
auto dilate_strides = Strides{2};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
dilate_strides,
|
||||
CoordinateDiff{0},
|
||||
CoordinateDiff{0},
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{2});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{0});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{0});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_window_dilated_padded)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -354,35 +166,6 @@ TEST(type_prop, conv_1d_deduce_window_dilated_padded)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_window_dilated_padded)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 100};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 10}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 87}); // output delta
|
||||
auto move_strides = Strides{1};
|
||||
auto dilate_strides = Strides{2};
|
||||
auto padding_below = CoordinateDiff{2};
|
||||
auto padding_above = CoordinateDiff{3};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
dilate_strides,
|
||||
padding_below,
|
||||
padding_above,
|
||||
Strides{1});
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{2});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{1});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{2});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_deduce_window_dilated_data_dilated_padded)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -411,36 +194,6 @@ TEST(type_prop, conv_1d_deduce_window_dilated_data_dilated_padded)
|
||||
EXPECT_EQ(conv->get_padding_above(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_1d_back_data_batch_deduce_window_dilated_data_dilated_padded)
|
||||
{
|
||||
// Deduce type
|
||||
Shape data_batch_shape{64, 3, 100};
|
||||
auto param0 = make_shared<op::Parameter>(element::f32, Shape{128, 3, 10}); // filters
|
||||
auto param1 = make_shared<op::Parameter>(element::f32, Shape{64, 128, 285}); // output delta
|
||||
auto move_strides = Strides{1};
|
||||
auto dilate_strides = Strides{2};
|
||||
auto padding_below = CoordinateDiff{2};
|
||||
auto padding_above = CoordinateDiff{3};
|
||||
auto data_dilate_strides = Strides{3};
|
||||
auto conv = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
|
||||
param0,
|
||||
param1,
|
||||
move_strides,
|
||||
dilate_strides,
|
||||
padding_below,
|
||||
padding_above,
|
||||
data_dilate_strides);
|
||||
EXPECT_EQ(conv->get_element_type(), element::f32);
|
||||
EXPECT_EQ(conv->get_shape(), data_batch_shape);
|
||||
|
||||
EXPECT_EQ(conv->get_window_movement_strides_forward(), Strides{1});
|
||||
EXPECT_EQ(conv->get_window_dilation_strides_forward(), Strides{2});
|
||||
EXPECT_EQ(conv->get_data_dilation_strides_forward(), Strides{3});
|
||||
|
||||
EXPECT_EQ(conv->get_padding_below_forward(), CoordinateDiff{2});
|
||||
EXPECT_EQ(conv->get_padding_above_forward(), CoordinateDiff{3});
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_2d_deduce)
|
||||
{
|
||||
// Deduce type
|
||||
@@ -2485,46 +2238,6 @@ TEST(type_prop, conv_partial_dynamic_et)
|
||||
PartialShape{64, 100, 1, Dimension::dynamic()}));
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_bprop_data_v1_output_partial_shape_dynamic)
|
||||
{
|
||||
Shape shape_filter{6, 3, 3, 3};
|
||||
auto filters = make_shared<op::Parameter>(element::f32, shape_filter);
|
||||
Shape shape_delta{2, 6, 3, 3};
|
||||
auto deltas = make_shared<op::Parameter>(element::f32, shape_delta);
|
||||
Shape shape_data_batch_shape{2, 3, 5, 5};
|
||||
auto data_batch_shape = make_shared<op::Parameter>(element::i64, Shape{2, 3, 5, 5});
|
||||
auto strides = Strides{1, 1};
|
||||
auto dilations = Strides{1, 1};
|
||||
auto padding_begin = CoordinateDiff{0, 0};
|
||||
auto padding_end = CoordinateDiff{0, 0};
|
||||
|
||||
auto conv1 = make_shared<op::v1::ConvolutionBackpropData>(
|
||||
deltas, filters, data_batch_shape, strides, padding_begin, padding_end, dilations);
|
||||
|
||||
ASSERT_TRUE(conv1->get_output_partial_shape(0).is_dynamic());
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_bprop_data_v1_output_partial_shape_dynamic_static_rank)
|
||||
{
|
||||
PartialShape shape_filter{20, 10, 3, 3};
|
||||
auto filters = make_shared<op::Parameter>(element::f32, shape_filter);
|
||||
PartialShape shape_delta{Dimension(), 20, 224, 224};
|
||||
auto deltas = make_shared<op::Parameter>(element::f32, shape_delta);
|
||||
auto strides = Strides{2, 2};
|
||||
auto dilations = Strides{1, 1};
|
||||
auto padding_begin = CoordinateDiff{1, 1};
|
||||
auto padding_end = CoordinateDiff{1, 1};
|
||||
|
||||
auto conv1 = make_shared<op::v1::ConvolutionBackpropData>(
|
||||
deltas, filters, strides, padding_begin, padding_end, dilations);
|
||||
|
||||
ASSERT_TRUE(conv1->get_output_partial_shape(0).rank().is_static());
|
||||
ASSERT_TRUE(conv1->get_output_partial_shape(0).rank().same_scheme(Rank{4}));
|
||||
ASSERT_TRUE(conv1->get_output_partial_shape(0).is_dynamic());
|
||||
ASSERT_TRUE(conv1->get_output_partial_shape(0).same_scheme(
|
||||
PartialShape{Dimension::dynamic(), 10, 447, 447}));
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_v1_partial_rank)
|
||||
{
|
||||
PartialShape data_batch_shape{PartialShape::dynamic()};
|
||||
@@ -2652,53 +2365,3 @@ TEST(type_prop, conv_v1_partial_data_shape_dynamic)
|
||||
ASSERT_EQ(conv->get_pads_begin(), (CoordinateDiff{}));
|
||||
ASSERT_EQ(conv->get_pads_end(), (CoordinateDiff{}));
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_bprop_v1_partial_auto_padding_upper)
|
||||
{
|
||||
const Shape shape1{1, 512, 1, 37};
|
||||
const Shape shape2{512, 256, 1, 1};
|
||||
const Shape shape3{2};
|
||||
Strides strides{1, 2};
|
||||
CoordinateDiff pads_begin{0, 0};
|
||||
CoordinateDiff pads_end{0, 0};
|
||||
Strides dilations{1, 1};
|
||||
const auto auto_pad = op::PadType::SAME_UPPER;
|
||||
|
||||
auto in1 = make_shared<op::Parameter>(element::f32, shape1);
|
||||
auto in2 = make_shared<op::Parameter>(element::f32, shape2);
|
||||
std::vector<int64_t> data = {1, 74};
|
||||
element::Type type = element::i64;
|
||||
auto in3 = make_shared<op::Constant>(type, shape3, data);
|
||||
|
||||
auto conv = make_shared<op::v1::ConvolutionBackpropData>(
|
||||
in1, in2, in3, strides, pads_begin, pads_end, dilations, auto_pad);
|
||||
conv->validate_and_infer_types();
|
||||
|
||||
ASSERT_EQ(conv->get_pads_begin(), (CoordinateDiff{0, 0}));
|
||||
ASSERT_EQ(conv->get_pads_end(), (CoordinateDiff{0, 0}));
|
||||
}
|
||||
|
||||
TEST(type_prop, conv_bprop_v1_partial_auto_padding_lower)
|
||||
{
|
||||
const Shape shape1{1, 512, 1, 37};
|
||||
const Shape shape2{512, 256, 1, 1};
|
||||
const Shape shape3{2};
|
||||
Strides strides{1, 2};
|
||||
CoordinateDiff pads_begin{0, 0};
|
||||
CoordinateDiff pads_end{0, 0};
|
||||
Strides dilations{1, 1};
|
||||
const auto auto_pad = op::PadType::SAME_LOWER;
|
||||
|
||||
auto in1 = make_shared<op::Parameter>(element::f32, shape1);
|
||||
auto in2 = make_shared<op::Parameter>(element::f32, shape2);
|
||||
std::vector<int64_t> data = {1, 74};
|
||||
element::Type type = element::i64;
|
||||
auto in3 = make_shared<op::Constant>(type, shape3, data);
|
||||
|
||||
auto conv = make_shared<op::v1::ConvolutionBackpropData>(
|
||||
in1, in2, in3, strides, pads_begin, pads_end, dilations, auto_pad);
|
||||
conv->validate_and_infer_types();
|
||||
|
||||
ASSERT_EQ(conv->get_pads_begin(), (CoordinateDiff{0, 0}));
|
||||
ASSERT_EQ(conv->get_pads_end(), (CoordinateDiff{0, 0}));
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -128,6 +128,12 @@ namespace ngraph
|
||||
std::cerr << "]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t get_value_map_size() const
|
||||
{
|
||||
return m_values.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& get(const std::string& name)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "ngraph/op/util/attr_types.hpp"
|
||||
#include "ngraph/opsets/opset1.hpp"
|
||||
|
||||
#include "util/visitor.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
using ngraph::test::NodeBuilder;
|
||||
|
||||
TEST(attributes, sqrt_op)
|
||||
{
|
||||
using namespace opset1;
|
||||
|
||||
NodeBuilder::get_ops().register_factory<Sqrt>();
|
||||
const auto data_input = make_shared<Parameter>(element::f32, Shape{1, 2, 3});
|
||||
const auto op = make_shared<Sqrt>(data_input);
|
||||
|
||||
NodeBuilder builder(op);
|
||||
const auto expected_attr_count = 0;
|
||||
|
||||
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "ngraph/op/util/attr_types.hpp"
|
||||
#include "ngraph/opsets/opset1.hpp"
|
||||
|
||||
#include "util/visitor.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
using ngraph::test::NodeBuilder;
|
||||
|
||||
TEST(attributes, transpose_op)
|
||||
{
|
||||
using namespace opset1;
|
||||
|
||||
NodeBuilder::get_ops().register_factory<Transpose>();
|
||||
const auto data_input = make_shared<Parameter>(element::f32, Shape{1, 2, 3});
|
||||
const auto axes_order_input = make_shared<Parameter>(element::i32, Shape{3});
|
||||
|
||||
const auto op = make_shared<Transpose>(data_input, axes_order_input);
|
||||
|
||||
NodeBuilder builder(op);
|
||||
const auto expected_attr_count = 0;
|
||||
|
||||
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
|
||||
}
|
||||
@@ -142,9 +142,6 @@ def run(args):
|
||||
logger.warning(f"Turn off threads pinning for {device} " +
|
||||
"device since multi-scenario with GPU device is used.")
|
||||
config[device]['CPU_BIND_THREAD'] = 'NO'
|
||||
else:
|
||||
## set to default value
|
||||
config[device]['CPU_BIND_THREAD'] = args.infer_threads_pinning
|
||||
|
||||
## for CPU execution, more throughput-oriented execution via streams
|
||||
set_throughput_streams()
|
||||
|
||||
@@ -91,8 +91,11 @@ def parse_args():
|
||||
args.add_argument('-nthreads', '--number_threads', type=int, required=False, default=None,
|
||||
help='Number of threads to use for inference on the CPU, GNA '
|
||||
'(including HETERO and MULTI cases).')
|
||||
args.add_argument('-pin', '--infer_threads_pinning', type=str, required=False, default='YES', choices=['YES', 'NO', 'NUMA'],
|
||||
help='Optional. Enable threads->cores (\'YES\' is default value), threads->(NUMA)nodes (\'NUMA\') or completely disable (\'NO\')'
|
||||
args.add_argument('-pin', '--infer_threads_pinning', type=str, required=False, choices=['YES', 'NO', 'NUMA', 'HYBRID_AWARE'],
|
||||
help='Optional. Enable threads->cores (\'YES\' which is OpenVINO runtime\'s default for conventional CPUs), '
|
||||
'threads->(NUMA)nodes (\'NUMA\'), '
|
||||
'threads->appropriate core types (\'HYBRID_AWARE\', which is OpenVINO runtime\'s default for Hybrid CPUs)'
|
||||
'or completely disable (\'NO\')'
|
||||
'CPU threads pinning for CPU-involved inference.')
|
||||
args.add_argument('-exec_graph_path', '--exec_graph_path', type=str, required=False,
|
||||
help='Optional. Path to a file where to store executable graph information serialized.')
|
||||
|
||||
Reference in new issue
Block a user