Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Xiaomi
Mace
提交
884267bf
Mace
项目概览
Xiaomi
/
Mace
通知
106
Star
40
Fork
27
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Mace
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
884267bf
编写于
12月 13, 2017
作者:
L
Liangliang He
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'gen_opencl_kernel_binary' into 'master'
Generate opencl kernel binary See merge request !155
上级
ecef3596
302c4d5b
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
153 addition
and
47 deletion
+153
-47
mace/core/runtime/opencl/opencl_runtime.cc
mace/core/runtime/opencl/opencl_runtime.cc
+150
-46
mace/core/runtime/opencl/opencl_runtime.h
mace/core/runtime/opencl/opencl_runtime.h
+3
-1
未找到文件。
mace/core/runtime/opencl/opencl_runtime.cc
浏览文件 @
884267bf
...
...
@@ -10,30 +10,74 @@
#include "mace/core/logging.h"
#include "mace/core/runtime/opencl/opencl_runtime.h"
#include <CL/opencl.h>
namespace
mace
{
namespace
{
bool
ReadSourceFile
(
const
std
::
string
&
filename
,
std
::
string
*
content
)
{
MACE_CHECK_NOTNULL
(
content
);
*
content
=
""
;
std
::
ifstream
ifs
(
filename
,
std
::
ifstream
::
in
);
bool
ReadFile
(
const
std
::
string
&
filename
,
bool
binary
,
std
::
vector
<
unsigned
char
>
*
content_ptr
)
{
MACE_CHECK_NOTNULL
(
content_ptr
);
std
::
ios_base
::
openmode
mode
=
std
::
ios
::
in
;
if
(
binary
)
{
mode
|=
std
::
ios
::
binary
;
}
std
::
ifstream
ifs
(
filename
,
mode
);
// Stop eating new lines and whitespace
ifs
.
unsetf
(
std
::
ios
::
skipws
);
if
(
!
ifs
.
is_open
())
{
LOG
(
ERROR
)
<<
"Failed to open file "
<<
filename
;
return
false
;
}
std
::
string
line
;
while
(
std
::
getline
(
ifs
,
line
))
{
*
content
+=
line
;
*
content
+=
"
\n
"
;
ifs
.
seekg
(
0
,
std
::
ios
::
end
);
const
size_t
filesize
=
ifs
.
tellg
();
if
(
filesize
>
10
*
1024
*
1024
)
{
LOG
(
ERROR
)
<<
"Filesize overflow 10MB"
;
return
false
;
}
content_ptr
->
reserve
(
filesize
);
ifs
.
seekg
(
0
,
std
::
ios
::
beg
);
content_ptr
->
insert
(
content_ptr
->
begin
(),
std
::
istreambuf_iterator
<
char
>
(
ifs
),
std
::
istreambuf_iterator
<
char
>
());
if
(
ifs
.
fail
())
{
LOG
(
ERROR
)
<<
"Failed to read from file "
<<
filename
;
return
false
;
}
ifs
.
close
();
return
true
;
}
bool
WriteFile
(
const
std
::
string
&
filename
,
bool
binary
,
const
std
::
vector
<
unsigned
char
>
&
content
)
{
std
::
ios_base
::
openmode
mode
=
std
::
ios
::
out
;
if
(
binary
)
{
mode
|=
std
::
ios
::
binary
;
}
std
::
ofstream
ofs
(
filename
,
mode
);
ofs
.
write
(
reinterpret_cast
<
const
char
*>
(
&
content
[
0
]),
content
.
size
()
*
sizeof
(
char
));
ofs
.
close
();
if
(
ofs
.
fail
())
{
LOG
(
ERROR
)
<<
"Failed to write to file "
<<
filename
;
return
false
;
}
return
true
;
}
}
// namespace
bool
OpenCLRuntime
::
enable_profiling_
=
false
;
std
::
unique_ptr
<
cl
::
Event
>
OpenCLRuntime
::
profiling_ev_
=
NULL
;
std
::
unique_ptr
<
cl
::
Event
>
OpenCLRuntime
::
profiling_ev_
=
nullptr
;
OpenCLRuntime
*
OpenCLRuntime
::
Get
()
{
static
std
::
once_flag
init_once
;
...
...
@@ -97,13 +141,9 @@ OpenCLRuntime *OpenCLRuntime::Get() {
return
instance
;
}
void
OpenCLRuntime
::
EnableProfiling
()
{
enable_profiling_
=
true
;
}
void
OpenCLRuntime
::
EnableProfiling
()
{
enable_profiling_
=
true
;
}
cl
::
Event
*
OpenCLRuntime
::
GetDefaultEvent
()
{
return
profiling_ev_
.
get
();
}
cl
::
Event
*
OpenCLRuntime
::
GetDefaultEvent
()
{
return
profiling_ev_
.
get
();
}
cl_ulong
OpenCLRuntime
::
GetEventProfilingStartInfo
()
{
MACE_CHECK
(
profiling_ev_
,
"is NULL, should enable profiling first."
);
...
...
@@ -115,8 +155,7 @@ cl_ulong OpenCLRuntime::GetEventProfilingEndInfo() {
return
profiling_ev_
->
getProfilingInfo
<
CL_PROFILING_COMMAND_END
>
();
}
OpenCLRuntime
::
OpenCLRuntime
(
cl
::
Context
context
,
cl
::
Device
device
,
OpenCLRuntime
::
OpenCLRuntime
(
cl
::
Context
context
,
cl
::
Device
device
,
cl
::
CommandQueue
command_queue
)
:
context_
(
context
),
device_
(
device
),
command_queue_
(
command_queue
)
{
const
char
*
kernel_path
=
getenv
(
"MACE_KERNEL_PATH"
);
...
...
@@ -137,37 +176,70 @@ cl::Program &OpenCLRuntime::program() {
}
// TODO(heliangliang) Support binary format
const
std
::
map
<
std
::
string
,
std
::
string
>
OpenCLRuntime
::
program_map_
=
{
{
"addn"
,
"addn.cl"
},
{
"batch_norm"
,
"batch_norm.cl"
},
{
"bias_add"
,
"bias_add.cl"
},
{
"buffer_to_image"
,
"buffer_to_image.cl"
},
{
"conv_2d"
,
"conv_2d.cl"
},
{
"conv_2d_1x1"
,
"conv_2d_1x1.cl"
},
{
"conv_2d_3x3"
,
"conv_2d_3x3.cl"
},
{
"depthwise_conv_3x3"
,
"depthwise_conv_3x3.cl"
},
{
"pooling"
,
"pooling.cl"
},
{
"relu"
,
"relu.cl"
},
{
"concat"
,
"concat.cl"
},
{
"resize_bilinear"
,
"resize_bilinear.cl"
},
{
"space_to_batch"
,
"space_to_batch.cl"
},
const
std
::
map
<
std
::
string
,
std
::
string
>
OpenCLRuntime
::
program_map_
=
{
{
"addn"
,
"addn.cl"
},
{
"batch_norm"
,
"batch_norm.cl"
},
{
"bias_add"
,
"bias_add.cl"
},
{
"buffer_to_image"
,
"buffer_to_image.cl"
},
{
"conv_2d"
,
"conv_2d.cl"
},
{
"conv_2d_1x1"
,
"conv_2d_1x1.cl"
},
{
"conv_2d_3x3"
,
"conv_2d_3x3.cl"
},
{
"depthwise_conv_3x3"
,
"depthwise_conv_3x3.cl"
},
{
"pooling"
,
"pooling.cl"
},
{
"relu"
,
"relu.cl"
},
{
"concat"
,
"concat.cl"
},
{
"resize_bilinear"
,
"resize_bilinear.cl"
},
{
"space_to_batch"
,
"space_to_batch.cl"
},
};
std
::
string
OpenCLRuntime
::
GenerateCLBinaryFilenamePrefix
(
const
std
::
string
&
filename_msg
)
{
std
::
string
filename_prefix
=
filename_msg
;
for
(
auto
it
=
filename_prefix
.
begin
();
it
!=
filename_prefix
.
end
();
++
it
)
{
if
(
*
it
==
' '
||
*
it
==
'-'
||
*
it
==
'='
)
{
*
it
=
'_'
;
}
}
return
filename_prefix
;
}
void
OpenCLRuntime
::
BuildProgram
(
const
std
::
string
&
program_file_name
,
const
std
::
string
&
binary_file_name_prefix
,
const
std
::
string
&
build_options
,
cl
::
Program
*
program
)
{
MACE_CHECK_NOTNULL
(
program
);
cl
::
Program
::
Sources
sources
;
std
::
string
filename
=
kernel_path_
+
program_file_name
;
std
::
string
kernel_source
;
MACE_CHECK
(
ReadSourceFile
(
filename
,
&
kernel_source
));
sources
.
push_back
({
kernel_source
.
c_str
(),
kernel_source
.
length
()});
std
::
string
source_filename
=
kernel_path_
+
program_file_name
;
std
::
string
binary_filename
=
kernel_path_
+
binary_file_name_prefix
+
".bin"
;
// Create program
bool
is_binary_filename_exist
=
std
::
ifstream
(
binary_filename
).
is_open
();
if
(
is_binary_filename_exist
)
{
VLOG
(
1
)
<<
"Create program with binary: "
<<
binary_filename
;
std
::
vector
<
unsigned
char
>
binaries
;
MACE_CHECK
(
ReadFile
(
binary_filename
,
true
,
&
binaries
));
*
program
=
cl
::
Program
(
this
->
context
(),
{
device
()},
{
binaries
});
}
else
if
(
std
::
ifstream
(
source_filename
).
is_open
())
{
VLOG
(
1
)
<<
"Create program with source: "
<<
source_filename
;
std
::
vector
<
unsigned
char
>
kernel_source
;
MACE_CHECK
(
ReadFile
(
source_filename
,
false
,
&
kernel_source
));
*
program
=
cl
::
Program
(
this
->
context
(),
sources
);
std
::
string
build_options_str
=
build_options
+
" -Werror -cl-mad-enable -cl-fast-relaxed-math -I"
+
kernel_path_
;
cl
::
Program
::
Sources
sources
;
sources
.
push_back
(
std
::
string
(
kernel_source
.
begin
(),
kernel_source
.
end
()));
*
program
=
cl
::
Program
(
this
->
context
(),
sources
);
}
else
{
LOG
(
FATAL
)
<<
"Failed to open kernel file "
<<
binary_filename
<<
" or "
<<
source_filename
;
}
// Build program
std
::
string
build_options_str
=
build_options
+
" -Werror -cl-mad-enable -cl-fast-relaxed-math -I"
+
kernel_path_
;
// TODO(heliangliang) -cl-unsafe-math-optimizations -cl-fast-relaxed-math
cl_int
ret
=
program
->
build
({
device
()},
build_options_str
.
c_str
());
if
(
ret
!=
CL_SUCCESS
)
{
...
...
@@ -179,11 +251,40 @@ void OpenCLRuntime::BuildProgram(const std::string &program_file_name,
}
LOG
(
FATAL
)
<<
"Build program failed: "
<<
ret
;
}
// Write binary if necessary
if
(
!
is_binary_filename_exist
)
{
size_t
device_list_size
=
1
;
std
::
unique_ptr
<
size_t
[]
>
program_binary_sizes
(
new
size_t
[
device_list_size
]);
cl_int
err
=
clGetProgramInfo
((
*
program
)(),
CL_PROGRAM_BINARY_SIZES
,
sizeof
(
size_t
)
*
device_list_size
,
program_binary_sizes
.
get
(),
nullptr
);
MACE_CHECK
(
err
==
CL_SUCCESS
)
<<
"Error code: "
<<
err
;
std
::
unique_ptr
<
std
::
unique_ptr
<
unsigned
char
[]
>
[]
>
program_binaries
(
new
std
::
unique_ptr
<
unsigned
char
[]
>
[
device_list_size
]);
for
(
cl_uint
i
=
0
;
i
<
device_list_size
;
++
i
)
{
program_binaries
[
i
]
=
std
::
unique_ptr
<
unsigned
char
[]
>
(
new
unsigned
char
[
program_binary_sizes
[
i
]]);
}
err
=
clGetProgramInfo
((
*
program
)(),
CL_PROGRAM_BINARIES
,
sizeof
(
unsigned
char
*
)
*
device_list_size
,
program_binaries
.
get
(),
nullptr
);
MACE_CHECK
(
err
==
CL_SUCCESS
)
<<
"Error code: "
<<
err
;
std
::
vector
<
unsigned
char
>
content
(
reinterpret_cast
<
unsigned
char
const
*>
(
program_binaries
[
0
].
get
()),
reinterpret_cast
<
unsigned
char
const
*>
(
program_binaries
[
0
].
get
())
+
program_binary_sizes
[
0
]);
MACE_CHECK
(
WriteFile
(
binary_filename
,
true
,
content
));
}
}
cl
::
Kernel
OpenCLRuntime
::
BuildKernel
(
const
std
::
string
&
program_name
,
const
std
::
string
&
kernel_name
,
const
std
::
set
<
std
::
string
>
&
build_options
)
{
cl
::
Kernel
OpenCLRuntime
::
BuildKernel
(
const
std
::
string
&
program_name
,
const
std
::
string
&
kernel_name
,
const
std
::
set
<
std
::
string
>
&
build_options
)
{
auto
kernel_program_it
=
program_map_
.
find
(
program_name
);
if
(
kernel_program_it
==
program_map_
.
end
())
{
MACE_CHECK
(
false
,
program_name
,
" opencl kernel doesn't exist."
);
...
...
@@ -191,7 +292,7 @@ cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name,
std
::
string
program_file_name
=
kernel_program_it
->
second
;
std
::
string
build_options_str
;
for
(
auto
&
option
:
build_options
)
{
for
(
auto
&
option
:
build_options
)
{
build_options_str
+=
" "
+
option
;
}
std
::
string
built_program_key
=
program_name
+
build_options_str
;
...
...
@@ -202,7 +303,10 @@ cl::Kernel OpenCLRuntime::BuildKernel(const std::string &program_name,
if
(
built_program_it
!=
built_program_map_
.
end
())
{
program
=
built_program_it
->
second
;
}
else
{
this
->
BuildProgram
(
program_file_name
,
build_options_str
,
&
program
);
std
::
string
binary_file_name_prefix
=
GenerateCLBinaryFilenamePrefix
(
built_program_key
);
this
->
BuildProgram
(
program_file_name
,
binary_file_name_prefix
,
build_options_str
,
&
program
);
built_program_map_
.
emplace
(
built_program_key
,
program
);
}
return
cl
::
Kernel
(
program
,
kernel_name
.
c_str
());
...
...
@@ -214,7 +318,7 @@ uint32_t OpenCLRuntime::GetDeviceMaxWorkGroupSize() {
return
static_cast
<
uint32_t
>
(
size
);
}
uint32_t
OpenCLRuntime
::
GetKernelMaxWorkGroupSize
(
const
cl
::
Kernel
&
kernel
)
{
uint32_t
OpenCLRuntime
::
GetKernelMaxWorkGroupSize
(
const
cl
::
Kernel
&
kernel
)
{
unsigned
long
long
size
=
0
;
kernel
.
getWorkGroupInfo
(
device_
,
CL_KERNEL_WORK_GROUP_SIZE
,
&
size
);
return
static_cast
<
uint32_t
>
(
size
);
...
...
mace/core/runtime/opencl/opencl_runtime.h
浏览文件 @
884267bf
...
...
@@ -44,9 +44,11 @@ class OpenCLRuntime {
OpenCLRuntime
(
const
OpenCLRuntime
&
)
=
delete
;
OpenCLRuntime
&
operator
=
(
const
OpenCLRuntime
&
)
=
delete
;
void
BuildProgram
(
const
std
::
string
&
kernel_name
,
void
BuildProgram
(
const
std
::
string
&
program_file_name
,
const
std
::
string
&
binary_file_name
,
const
std
::
string
&
build_options
,
cl
::
Program
*
program
);
std
::
string
GenerateCLBinaryFilenamePrefix
(
const
std
::
string
&
filename_msg
);
private:
static
bool
enable_profiling_
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录