Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Steve Yoo committed 2021-04-29 07:15:08 +09:00
commit f569dbc739
90 files changed
+3548 -1718

No files matched your search

-4
View File
@@ -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)
-4
View File
@@ -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)
+1 -6
View File
@@ -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: |
+52 -10
View File
@@ -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
+48 -12
View File
@@ -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,7 +1,7 @@
bandit
black
flake8
flake8-annotations-complexity
flake8-bandit
flake8-broken-line
flake8-bugbear
flake8-class-attributes-order
@@ -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,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
@@ -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
@@ -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
@@ -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']
@@ -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(&currentCoreSet);
int phys_cores = CPU_COUNT(&currentCoreSet);
#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 {
+14 -11
View File
@@ -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, &register_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,
&register_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).
@@ -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
@@ -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;
@@ -0,0 +1,4 @@
# Hung:
.*AvgPool_1199829.*
.*AvgPool_1201153.*
.*ROIPooling_1199827.*
@@ -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.*
@@ -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.*
@@ -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.*
@@ -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);
@@ -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,
@@ -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;
}
@@ -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
@@ -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)))
+13 -4
View File
@@ -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
View File
@@ -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)
+1
View File
@@ -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}
)
+1
View 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)
+5
View File
@@ -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}>
+1 -1
View File
@@ -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
+172 -81
View File
@@ -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>
@@ -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
+7 -53
View File
@@ -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;
}
+830
View File
@@ -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,
&register_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
{
-2
View File
@@ -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:
+3
View File
@@ -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
)
@@ -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
}
+13 -1
View File
@@ -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(
-337
View File
@@ -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
+6
View File
@@ -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)
{
+29
View File
@@ -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);
}
+31
View File
@@ -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);
}
-3
View File
@@ -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()
+5 -2
View File
@@ -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.')