Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ModelZoo
ResNet50_migraphx
Commits
a27c38fe
Commit
a27c38fe
authored
Nov 06, 2023
by
liucong
Browse files
加入offload为false的工程示例
parent
c1f9a061
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
243 additions
and
20 deletions
+243
-20
Doc/Tutorial_Cpp.md
Doc/Tutorial_Cpp.md
+29
-7
Doc/Tutorial_Python.md
Doc/Tutorial_Python.md
+35
-0
Python/Classifier_OffloadFalse.py
Python/Classifier_OffloadFalse.py
+114
-0
README.md
README.md
+13
-2
Resource/Configuration.xml
Resource/Configuration.xml
+1
-0
Src/Classifier.cpp
Src/Classifier.cpp
+51
-11
No files found.
Doc/Tutorial_Cpp.md
View file @
a27c38fe
...
...
@@ -86,6 +86,7 @@ blobFromImagesWithParams()函数支持多个输入图像,首先对输入图像
...
<
UseInt8
>
0
</
UseInt8
>
// 设置为1时,开启INT8量化
<
UseFP16
>
0
</
UseFP16
>
// 设置为1时,开启FP16量化
...
</
Classifier
>
</
opencv_storage
>
```
...
...
@@ -135,21 +136,42 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector
// 预处理
// 创建输入数据
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
};
migraphx
::
argument
result
;
if
(
useoffloadcopy
)
{
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
};
// 推理
std
::
vector
<
std
::
string
>
outputNames
=
{
"resnetv24_dense0_fwd"
};
// 设置返回的输出节点
std
::
vector
<
migraphx
::
argument
>
results
=
net
.
eval
(
inputData
,
outputNames
);
result
=
results
[
0
];
// 获取第一个输出节点的数据
}
else
{
// 为输出节点分配device内存,用于保存输出数据
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
modelData
=
CreateOutputData
(
net
);
// 将输入转换为device数据
migraphx
::
argument
inputData
=
migraphx
::
gpu
::
to_gpu
(
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
});
//
推理
std
::
vector
<
migraphx
::
argument
>
results
=
net
.
eval
(
inputData
)
;
//
使用device数据作为输入数据,inputData.data()返回的是device地址
modelData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
inputData
.
data
()}
;
// 获取输出节点的属性
migraphx
::
argument
result
=
results
[
0
];
// 获取第一个输出节点的数据
// 推理
std
::
vector
<
std
::
string
>
outputNames
=
{
"resnetv24_dense0_fwd"
};
// 设置返回的输出节点
std
::
vector
<
migraphx
::
argument
>
results
=
net
.
eval
(
modelData
,
outputNames
);
result
=
migraphx
::
gpu
::
from_gpu
(
results
[
0
]);
// 将第一个输出节点的数据拷贝到host端
}
...
}
```
-
inputData表示MIGraphX的输入数据,inputData是一个映射关系,每个输入节点名都会对应一个输入数据,如果有多个输入,则需要为每个输入节点名创建数据,inputName表示输入节点名,migraphx::argument{inputShape, (float
*
)inputBlob.data}表示该节点名对应的数据,这里是通过前面预处理的数据inputBlob来创建的,第一个参数表示数据的shape,第二个参数表示数据指针。
-
输入数据根据是否需要数据拷贝分为两种:offload=true、offload=false。当offload为true时,执行if分支,不需要进行内存拷贝,
inputData表示MIGraphX的输入数据,inputData是一个映射关系,每个输入节点名都会对应一个输入数据,如果有多个输入,则需要为每个输入节点名创建数据,inputName表示输入节点名,migraphx::argument{inputShape, (float
*
)inputBlob.data}表示该节点名对应的数据,这里是通过前面预处理的数据inputBlob来创建的,第一个参数表示数据的shape,第二个参数表示数据指针。
当offload为false时,执行else分支,需要进行内存拷贝,为输入节点和输出节点分配device内存,用来保存输入数据和输出数据,使用device数据作为输入数据,执行推理。
-
net.eval(inputData)返回模型的推理结果,由于这里只有一个输出节点,所以std::vector中只有一个数据,results[0]表示第一个输出节点,这里对应resnetv24_dense0_fwd节点,获取输出数据。
另外,如果想要指定输出节点,可以在eval()方法中通过提供outputNames参数来实现:
...
...
Doc/Tutorial_Python.md
View file @
a27c38fe
...
...
@@ -109,6 +109,8 @@ if __name__ == '__main__':
```
python
if
__name__
==
'__main__'
:
...
# 编译
model
.
compile
(
t
=
migraphx
.
get_target
(
"gpu"
),
device_id
=
0
)
# device_id: 设置GPU设备,默认为0号设备
# 预处理
pathOfImage
=
"../Resource/Images/ImageNet_01.jpg"
...
...
@@ -129,3 +131,36 @@ if __name__ == '__main__':
-
Preprocessing()函数返回输入数据(numpy类型),然后通过{inputName: migraphx.argument(image)}构造一个字典输入模型执行推理,如果模型有多个输入,则在字典中需要添加多个输入数据。
-
model.run()返回模型的推理结果,返回结果是一个list类型,results[0]表示第一个输出节点的输出,是一个migraphx.argument类型,由于示例模型只有一个输出节点,所以results[0]对应resnetv24_dense0_fwd节点。最后,通过np.array(result)获取分类结果。
在Classifier_OffloadFalse.py脚本中,主要在推理阶段有所不同,需要进行内存拷贝。
```
python
if
__name__
==
'__main__'
:
...
# 编译
model
.
compile
(
t
=
migraphx
.
get_target
(
"gpu"
),
offload_copy
=
False
,
device_id
=
0
)
# device_id: 设置GPU设备,默认为0号设备
# 为输出节点分配device内存,用于保存输出数据
modelData
=
AllocateOutputMemory
(
model
)
# 预处理并转换为NCHW
pathOfImage
=
"../Resource/Images/ImageNet_01.jpg"
image
=
Preprocessing
(
pathOfImage
)
modelData
[
inputName
]
=
migraphx
.
to_gpu
(
migraphx
.
argument
(
image
))
# 推理
results
=
model
.
run
(
modelData
)
# 获取输出节点属性
result
=
migraphx
.
from_gpu
(
results
[
0
])
# 获取第一个输出节点的数据,migraphx.argument类型
outputShape
=
result
.
get_shape
()
# 输出节点的shape,migraphx.shape类型
outputSize
=
outputShape
.
lens
()
# 每一维大小,维度顺序为(N,C,H,W),list类型
numberOfOutput
=
outputShape
.
elements
()
# 输出节点元素的个数
# 获取分类结果
print
(
np
.
array
(
result
))
```
-
AllocateOutputMemory()函数主要用于为输出节点分配device内存,用来保存输出数据。
-
Preprocessing()函数返回输入数据后,通过migraphx.to_gpu(migraphx.argument(image))方法,将输入数据转换为device数据。
\ No newline at end of file
Python/Classifier_OffloadFalse.py
0 → 100644
View file @
a27c38fe
# -*- coding: utf-8 -*-
"""
offload为false时的分类器示例
"""
import
argparse
import
cv2
import
numpy
as
np
import
migraphx
def
AllocateOutputMemory
(
model
):
outputData
=
{}
for
key
in
model
.
get_outputs
().
keys
():
outputData
[
key
]
=
migraphx
.
allocate_gpu
(
s
=
model
.
get_outputs
()[
key
])
return
outputData
def
Preprocessing
(
pathOfImage
):
# 读取图像
image
=
cv2
.
imread
(
pathOfImage
,
cv2
.
IMREAD_COLOR
)
image
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_BGR2RGB
)
# 调整大小,使短边为256,保持长宽比
ratio
=
float
(
256
)
/
min
(
image
.
shape
[
0
],
image
.
shape
[
1
])
if
image
.
shape
[
0
]
>
image
.
shape
[
1
]:
new_size
=
[
int
(
round
(
ratio
*
image
.
shape
[
0
])),
256
]
else
:
new_size
=
[
256
,
int
(
round
(
ratio
*
image
.
shape
[
1
]))]
image
=
np
.
array
(
cv2
.
resize
(
image
,
(
new_size
[
1
],
new_size
[
0
])))
# 裁剪中心窗口为224*224
h
,
w
,
c
=
image
.
shape
start_x
=
w
//
2
-
224
//
2
start_y
=
h
//
2
-
224
//
2
image
=
image
[
start_y
:
start_y
+
224
,
start_x
:
start_x
+
224
,
:]
# transpose
image
=
image
.
transpose
(
2
,
0
,
1
)
# 将输入数据转换为float32
img_data
=
image
.
astype
(
'float32'
)
# normalize
mean_vec
=
np
.
array
([
123.675
,
116.28
,
103.53
])
stddev_vec
=
np
.
array
([
58.395
,
57.12
,
57.375
])
norm_img_data
=
np
.
zeros
(
img_data
.
shape
).
astype
(
'float32'
)
for
i
in
range
(
img_data
.
shape
[
0
]):
norm_img_data
[
i
,:,:]
=
(
img_data
[
i
,:,:]
-
mean_vec
[
i
])
/
stddev_vec
[
i
]
# 调整尺寸
norm_img_data
=
norm_img_data
.
reshape
(
1
,
3
,
224
,
224
).
astype
(
'float32'
)
return
norm_img_data
if
__name__
==
'__main__'
:
# 量化方法选项
use_int8
=
False
use_fp16
=
False
# 设置最大输入shape
maxInput
=
{
"data"
:[
1
,
3
,
224
,
224
]}
# 加载模型
model
=
migraphx
.
parse_onnx
(
"../Resource/Models/resnet50-v2-7.onnx"
,
map_input_dims
=
maxInput
)
# 获取模型输入/输出节点信息
print
(
"inputs:"
)
inputs
=
model
.
get_inputs
()
for
key
,
value
in
inputs
.
items
():
print
(
"{}:{}"
.
format
(
key
,
value
))
print
(
"outputs:"
)
outputs
=
model
.
get_outputs
()
for
key
,
value
in
outputs
.
items
():
print
(
"{}:{}"
.
format
(
key
,
value
))
inputName
=
model
.
get_parameter_names
()[
0
]
inputShape
=
inputs
[
inputName
].
lens
()
# INT8量化
if
use_int8
:
dic
=
dict
()
testofImage
=
"../Resource/Images/ImageNet_test.jpg"
testimage
=
Preprocessing
(
testofImage
)
dic
[
inputName
]
=
migraphx
.
argument
(
testimage
)
calibration
=
[
dic
]
migraphx
.
quantize_int8
(
model
,
migraphx
.
get_target
(
"gpu"
),
calibration
)
if
use_fp16
:
migraphx
.
quantize_fp16
(
model
)
# 编译
model
.
compile
(
t
=
migraphx
.
get_target
(
"gpu"
),
offload_copy
=
False
,
device_id
=
0
)
# device_id: 设置GPU设备,默认为0号设备
# 为输出节点分配device内存,用于保存输出数据
modelData
=
AllocateOutputMemory
(
model
)
# 预处理并转换为NCHW
pathOfImage
=
"../Resource/Images/ImageNet_01.jpg"
image
=
Preprocessing
(
pathOfImage
)
modelData
[
inputName
]
=
migraphx
.
to_gpu
(
migraphx
.
argument
(
image
))
# 推理
results
=
model
.
run
(
modelData
)
# 获取输出节点属性
result
=
migraphx
.
from_gpu
(
results
[
0
])
# 获取第一个输出节点的数据,migraphx.argument类型
outputShape
=
result
.
get_shape
()
# 输出节点的shape,migraphx.shape类型
outputSize
=
outputShape
.
lens
()
# 每一维大小,维度顺序为(N,C,H,W),list类型
numberOfOutput
=
outputShape
.
elements
()
# 输出节点元素的个数
# 获取分类结果
print
(
np
.
array
(
result
))
\ No newline at end of file
README.md
View file @
a27c38fe
...
...
@@ -74,9 +74,18 @@ cd Python/
# 安装依赖
pip
install
-
r
requirements
.
txt
-
i
https
:
//
pypi
.
tuna
.
tsinghua
.
edu
.
cn
/
simple
# 运行示例
```
1.offload为true的模型推理
```
python Classifier.py
```
2.
offload为false的模型推理
```
python Classifier_OffloadFalse.py
```
### C++版本推理
...
...
@@ -124,6 +133,8 @@ cd build/
.
/
ResNet50
```
默认offload为true,如果想要offload为false,可以在./Resource/Configuration.xmlwen文件中修改Useoffloadcopy为1,再执行示例程序。
## result
### Python版本
...
...
Resource/Configuration.xml
View file @
a27c38fe
...
...
@@ -6,6 +6,7 @@
<ModelPath>
"../Resource/Models/resnet50-v2-7.onnx"
</ModelPath>
<UseInt8>
0
</UseInt8>
<!--是否使用int8,不支持-->
<UseFP16>
0
</UseFP16>
<!--是否使用FP16-->
<Useoffloadcopy>
0
</Useoffloadcopy>
<!--是否使用offloadcopy-->
</Classifier>
</opencv_storage>
Src/Classifier.cpp
View file @
a27c38fe
...
...
@@ -3,7 +3,7 @@
#include <migraphx/onnx.hpp>
#include <migraphx/gpu/target.hpp>
#include <migraphx/quantization.hpp>
#include <migraphx/gpu/hip.hpp>
#include <Filesystem.h>
#include <SimpleLog.h>
#include <algorithm>
...
...
@@ -42,6 +42,7 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat
std
::
string
modelPath
=
(
std
::
string
)
netNode
[
"ModelPath"
];
useInt8
=
(
bool
)(
int
)
netNode
[
"UseInt8"
];
useFP16
=
(
bool
)(
int
)
netNode
[
"UseFP16"
];
useoffloadcopy
=
(
bool
)(
int
)
netNode
[
"Useoffloadcopy"
];
// 设置最大输入shape
migraphx
::
onnx_options
onnx_options
;
...
...
@@ -142,14 +143,30 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat
// 编译模型
migraphx
::
compile_options
options
;
options
.
device_id
=
0
;
// 设置GPU设备,默认为0号设备
options
.
offload_copy
=
true
;
if
(
useoffloadcopy
)
{
options
.
offload_copy
=
true
;
}
else
{
options
.
offload_copy
=
false
;
}
net
.
compile
(
gpuTarget
,
options
);
LOG_INFO
(
stdout
,
"succeed to compile model: %s
\n
"
,
GetFileName
(
modelPath
).
c_str
());
// warm up
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
};
net
.
eval
(
inputData
);
if
(
useoffloadcopy
)
{
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
};
net
.
eval
(
inputData
);
}
else
{
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
modelData_warm
=
CreateOutputData
(
net
);
modelData_warm
[
inputName
]
=
migraphx
::
gpu
::
to_gpu
(
migraphx
::
argument
{
inputShape
});
net
.
eval
(
modelData_warm
);
}
// log
LOG_INFO
(
stdout
,
"InputSize:%dx%d
\n
"
,
inputSize
.
width
,
inputSize
.
height
);
...
...
@@ -206,14 +223,37 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector
blobFromImagesWithParams
(
image
,
inputBlob
,
image2BlobParams
);
// 创建输入数据
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
};
migraphx
::
argument
result
;
if
(
useoffloadcopy
)
{
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
};
// 推理
std
::
vector
<
migraphx
::
argument
>
results
=
net
.
eval
(
inputData
);
// 推理
std
::
vector
<
std
::
string
>
outputNames
=
{
"resnetv24_dense0_fwd"
};
// 设置返回的输出节点
std
::
vector
<
migraphx
::
argument
>
results
=
net
.
eval
(
inputData
,
outputNames
);
result
=
results
[
0
];
// 获取第一个输出节点的数据
}
else
{
// 为输出节点分配device内存,用于保存输出数据
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
modelData
=
CreateOutputData
(
net
);
// 将输入转换为device数据
migraphx
::
argument
inputData
=
migraphx
::
gpu
::
to_gpu
(
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
});
// 使用device数据作为输入数据,inputData.data()返回的是device地址
modelData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
inputData
.
data
()};
// 推理
std
::
vector
<
std
::
string
>
outputNames
=
{
"resnetv24_dense0_fwd"
};
// 设置返回的输出节点
std
::
vector
<
migraphx
::
argument
>
results
=
net
.
eval
(
modelData
,
outputNames
);
result
=
migraphx
::
gpu
::
from_gpu
(
results
[
0
]);
// 将第一个输出节点的数据拷贝到host端
}
// 获取输出节点的属性
migraphx
::
argument
result
=
results
[
0
];
// 获取第一个输出节点的数据
migraphx
::
shape
outputShape
=
result
.
get_shape
();
// 输出节点的shape
std
::
vector
<
std
::
size_t
>
outputSize
=
outputShape
.
lens
();
// 每一维大小,维度顺序为(N,C,H,W)
int
numberOfOutput
=
outputShape
.
elements
();
// 输出节点元素的个数
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment