Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Crayon鑫
Paddle
提交
01e1cdac
P
Paddle
项目概览
Crayon鑫
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
01e1cdac
编写于
6月 10, 2019
作者:
Y
Yan Chunwei
提交者:
GitHub
6月 10, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
init code gen for light framework(#17905)
上级
71fcb968
变更
29
显示空白变更内容
内联
并排
Showing
29 changed file
with
1145 addition
and
58 deletion
+1145
-58
paddle/fluid/lite/CMakeLists.txt
paddle/fluid/lite/CMakeLists.txt
+37
-5
paddle/fluid/lite/api/cxx_api_test.cc
paddle/fluid/lite/api/cxx_api_test.cc
+1
-0
paddle/fluid/lite/core/CMakeLists.txt
paddle/fluid/lite/core/CMakeLists.txt
+2
-3
paddle/fluid/lite/core/context.h
paddle/fluid/lite/core/context.h
+5
-0
paddle/fluid/lite/core/hvy_tensor.h
paddle/fluid/lite/core/hvy_tensor.h
+9
-1
paddle/fluid/lite/core/kernel.h
paddle/fluid/lite/core/kernel.h
+1
-1
paddle/fluid/lite/core/lite_tensor.h
paddle/fluid/lite/core/lite_tensor.h
+8
-0
paddle/fluid/lite/core/op_lite.cc
paddle/fluid/lite/core/op_lite.cc
+11
-3
paddle/fluid/lite/core/op_registry.h
paddle/fluid/lite/core/op_registry.h
+3
-6
paddle/fluid/lite/core/scope.cc
paddle/fluid/lite/core/scope.cc
+7
-1
paddle/fluid/lite/core/target_wrapper.h
paddle/fluid/lite/core/target_wrapper.h
+40
-1
paddle/fluid/lite/core/tensor.h
paddle/fluid/lite/core/tensor.h
+19
-11
paddle/fluid/lite/core/variable.h
paddle/fluid/lite/core/variable.h
+1
-1
paddle/fluid/lite/gen_code/CMakeLists.txt
paddle/fluid/lite/gen_code/CMakeLists.txt
+24
-0
paddle/fluid/lite/gen_code/gen_code.cc
paddle/fluid/lite/gen_code/gen_code.cc
+193
-0
paddle/fluid/lite/gen_code/gen_code.h
paddle/fluid/lite/gen_code/gen_code.h
+254
-0
paddle/fluid/lite/gen_code/gen_code_test.cc
paddle/fluid/lite/gen_code/gen_code_test.cc
+139
-0
paddle/fluid/lite/gen_code/generated_code_test.cc
paddle/fluid/lite/gen_code/generated_code_test.cc
+46
-0
paddle/fluid/lite/gen_code/paddle_infer.cc
paddle/fluid/lite/gen_code/paddle_infer.cc
+139
-0
paddle/fluid/lite/gen_code/paddle_infer.h
paddle/fluid/lite/gen_code/paddle_infer.h
+70
-0
paddle/fluid/lite/kernels/x86/CMakeLists.txt
paddle/fluid/lite/kernels/x86/CMakeLists.txt
+1
-1
paddle/fluid/lite/model_parser/cpp/op_desc.cc
paddle/fluid/lite/model_parser/cpp/op_desc.cc
+8
-6
paddle/fluid/lite/model_parser/pb/op_desc.cc
paddle/fluid/lite/model_parser/pb/op_desc.cc
+1
-1
paddle/fluid/lite/operators/feed_op.cc
paddle/fluid/lite/operators/feed_op.cc
+2
-2
paddle/fluid/lite/operators/mul_op.h
paddle/fluid/lite/operators/mul_op.h
+4
-3
paddle/fluid/lite/tools/build.sh
paddle/fluid/lite/tools/build.sh
+23
-11
paddle/fluid/lite/utils/CMakeLists.txt
paddle/fluid/lite/utils/CMakeLists.txt
+1
-1
paddle/fluid/lite/utils/string.cc
paddle/fluid/lite/utils/string.cc
+19
-0
paddle/fluid/lite/utils/string.h
paddle/fluid/lite/utils/string.h
+77
-0
未找到文件。
paddle/fluid/lite/CMakeLists.txt
浏览文件 @
01e1cdac
...
...
@@ -34,7 +34,7 @@ endfunction()
function
(
lite_deps TARGET
)
set
(
options
""
)
set
(
oneValueArgs
""
)
set
(
multiValueArgs DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS ARGS
)
set
(
multiValueArgs DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS
LIGHT_DEPS HVY_DEPS
ARGS
)
cmake_parse_arguments
(
lite_deps
"
${
options
}
"
"
${
oneValueArgs
}
"
"
${
multiValueArgs
}
"
${
ARGN
}
)
set
(
deps
${
lite_deps_DEPS
}
)
...
...
@@ -63,14 +63,35 @@ function (lite_deps TARGET)
endforeach
(
var
)
endif
()
if
(
LITE_WITH_LIGHT_WEIGHT_FRAMEWORK
)
foreach
(
var
${
lite_deps_LIGHT_DEPS
}
)
set
(
deps
${
deps
}
${
var
}
)
endforeach
(
var
)
endif
()
if
(
NOT LITE_WITH_LIGHT_WEIGHT_FRAMEWORK
)
foreach
(
var
${
lite_deps_HVY_DEPS
}
)
set
(
deps
${
deps
}
${
var
}
)
endforeach
(
var
)
endif
()
set
(
${
TARGET
}
${
deps
}
PARENT_SCOPE
)
endfunction
()
# cc_library with branch support.
# The branches:
# X86_DEPS: works only when LITE_WITH_X86 is ON.
# CUDA_DEPS: LITE_WITH_CUDA
# ARM_DEPS: LITE_WITH_ARM
# PROFILE_DEPS: LITE_WITH_PROFILE
# LIGHT_DEPS: LITE_WITH_LIGHT_WEIGHT_FRAMEWORK
# HVY_DEPS: NOT LITE_WITH_LIGHT_WEIGHT_FRAMEWORK
function
(
lite_cc_library TARGET
)
set
(
options
""
)
set
(
oneValueArgs
""
)
set
(
multiValueArgs SRCS DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS ARGS
)
set
(
multiValueArgs SRCS DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS LIGHT_DEPS
HVY_DEPS ARGS
)
cmake_parse_arguments
(
args
"
${
options
}
"
"
${
oneValueArgs
}
"
"
${
multiValueArgs
}
"
${
ARGN
}
)
set
(
deps
""
)
...
...
@@ -79,7 +100,10 @@ function(lite_cc_library TARGET)
X86_DEPS
${
args_X86_DEPS
}
CUDA_DEPS
${
args_CUDA_DEPS
}
ARM_DEPS
${
args_ARM_DEPS
}
PROFILE_DEPS
${
args_PROFILE_DEPS
}
)
PROFILE_DEPS
${
args_PROFILE_DEPS
}
LIGHT_DEPS
${
args_LIGHT_DEPS
}
HVY_DEPS
${
args_HVY_DEPS
}
)
cc_library
(
${
TARGET
}
SRCS
${
args_SRCS
}
DEPS
${
deps
}
${
args_DEPS
}
)
endfunction
()
...
...
@@ -87,7 +111,8 @@ endfunction()
function
(
lite_cc_binary TARGET
)
set
(
options
""
)
set
(
oneValueArgs
""
)
set
(
multiValueArgs SRCS DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS ARGS
)
set
(
multiValueArgs SRCS DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS
LIGHT_DEPS HVY_DEPS ARGS
)
cmake_parse_arguments
(
args
"
${
options
}
"
"
${
oneValueArgs
}
"
"
${
multiValueArgs
}
"
${
ARGN
}
)
set
(
deps
""
)
...
...
@@ -97,6 +122,8 @@ function(lite_cc_binary TARGET)
CUDA_DEPS
${
args_CUDA_DEPS
}
ARM_DEPS
${
args_ARM_DEPS
}
PROFILE_DEPS
${
args_PROFILE_DEPS
}
LIGHT_DEPS
${
args_LIGHT_DEPS
}
HVY_DEPS
${
args_HVY_DEPS
}
)
cc_binary
(
${
TARGET
}
SRCS
${
args_SRCS
}
DEPS
${
deps
}
${
args_DEPS
}
)
endfunction
()
...
...
@@ -112,7 +139,9 @@ endfunction()
function
(
lite_cc_test TARGET
)
set
(
options
""
)
set
(
oneValueArgs
""
)
set
(
multiValueArgs SRCS DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS ARGS
)
set
(
multiValueArgs SRCS DEPS X86_DEPS CUDA_DEPS ARM_DEPS PROFILE_DEPS
LIGHT_DEPS HVY_DEPS
ARGS
)
cmake_parse_arguments
(
args
"
${
options
}
"
"
${
oneValueArgs
}
"
"
${
multiValueArgs
}
"
${
ARGN
}
)
set
(
deps
""
)
...
...
@@ -122,6 +151,8 @@ function(lite_cc_test TARGET)
CUDA_DEPS
${
args_CUDA_DEPS
}
ARM_DEPS
${
args_ARM_DEPS
}
PROFILE_DEPS
${
args_PROFILE_DEPS
}
LIGHT_DEPS
${
args_LIGHT_DEPS
}
HVY_DEPS
${
args_HVY_DEPS
}
)
_lite_cc_test
(
${
TARGET
}
SRCS
${
args_SRCS
}
DEPS
${
deps
}
ARGS
${
args_ARGS
}
)
register_test_offline
(
"
${
TARGET
}
"
)
...
...
@@ -137,3 +168,4 @@ add_subdirectory(kernels)
add_subdirectory
(
model_parser
)
add_subdirectory
(
utils
)
add_subdirectory
(
api
)
add_subdirectory
(
gen_code
)
paddle/fluid/lite/api/cxx_api_test.cc
浏览文件 @
01e1cdac
...
...
@@ -76,6 +76,7 @@ TEST(CXXApi, save_model) {
predictor
.
Build
(
FLAGS_model_dir
,
Place
{
TARGET
(
kCUDA
),
PRECISION
(
kFloat
)},
valid_places
);
LOG
(
INFO
)
<<
"Save optimized model to "
<<
FLAGS_optimized_model
;
predictor
.
SaveModel
(
FLAGS_optimized_model
);
}
#endif // LITE_WITH_LIGHT_WEIGHT_FRAMEWORK
...
...
paddle/fluid/lite/core/CMakeLists.txt
浏览文件 @
01e1cdac
...
...
@@ -8,7 +8,7 @@ lite_cc_library(target_wrapper_lite SRCS target_wrapper.cc
lite_cc_library
(
memory_lite SRCS memory.cc DEPS target_wrapper_lite
)
lite_cc_library
(
lite_tensor SRCS lite_tensor.cc DEPS memory_lite target_wrapper_lite
)
if
(
NOT LITE_WITH_LIGHT_WEIGHT_FRAMEWORK
)
cc_library
(
hvy_tensor SRCS hvy_tensor.cc DEPS lod_tensor
)
lite_cc_library
(
hvy_tensor SRCS hvy_tensor.cc DEPS lod_tensor HVY_DEPS framework_proto
)
endif
()
if
(
LITE_WITH_LIGHT_WEIGHT_FRAMEWORK
)
...
...
@@ -26,8 +26,7 @@ cc_library(scope_lite SRCS scope.cc DEPS ${tensor_lite})
cc_library
(
cpu_info_lite SRCS cpu_info.cc
)
cc_library
(
context_lite SRCS context.cc DEPS
${
tensor_lite
}
any_lite cpu_info_lite
)
cc_library
(
op_lite SRCS op_lite.cc DEPS scope_lite op_registry_lite target_wrapper_lite
cpp_op_desc_lite
${
tensor_lite
}
)
cpp_op_desc_lite
${
tensor_lite
}
)
cc_library
(
types_lite SRCS types.cc
)
cc_library
(
type_system SRCS type_system.cc DEPS
${
tensor_lite
}
target_wrapper_lite
)
...
...
paddle/fluid/lite/core/context.h
浏览文件 @
01e1cdac
...
...
@@ -173,6 +173,11 @@ class Context<TargetType::kX86> {
new
::
paddle
::
framework
::
ExecutionContext
(
*
x86_device_context_
));
}
Context
(
Context
&&
ctx
)
{
x86_device_context_
=
std
::
move
(
ctx
.
x86_device_context_
);
x86_execution_context_
=
std
::
move
(
ctx
.
x86_execution_context_
);
}
// NOTE: InitOnce should only be used by ContextScheduler
void
InitOnce
()
{}
...
...
paddle/fluid/lite/core/hvy_tensor.h
浏览文件 @
01e1cdac
...
...
@@ -21,6 +21,7 @@
#pragma once
#include <vector>
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/lite/core/target_wrapper.h"
#include "paddle/fluid/lite/core/tensor.h"
namespace
paddle
{
...
...
@@ -65,6 +66,14 @@ class TensorHvy : public TensorBase<TensorHvy> {
using
DDimT
=
DDimHvy
;
using
LoDT
=
framework
::
LoD
;
template
<
typename
DType
,
typename
DimT
,
TargetType
Target
>
void
Assign
(
DType
*
data
,
const
DimT
&
dim
)
{
Resize
(
dim
);
auto
*
dst
=
mutable_data
<
DType
>
(
Target
);
CopySync
<
Target
>
(
dst
,
data
,
dim
.
production
()
*
sizeof
(
DType
),
IoDirection
::
HtoD
);
}
TargetType
target
()
const
{
if
(
platform
::
is_gpu_place
(
data_
.
place
()))
{
return
TARGET
(
kCUDA
);
...
...
@@ -95,7 +104,6 @@ class TensorHvy : public TensorBase<TensorHvy> {
const
void
*
raw_data
()
const
{
return
data_
.
raw_data
();
}
void
Resize
(
const
DDimHvy
&
dims
)
{
LOG
(
INFO
)
<<
"dims.size "
<<
dims
.
size
();
data_
.
Resize
(
framework
::
make_ddim
(
dims
.
Vectorize
()));
}
...
...
paddle/fluid/lite/core/kernel.h
浏览文件 @
01e1cdac
...
...
@@ -150,7 +150,7 @@ class KernelBase {
void
Torch
()
{}
protected:
std
::
unique_ptr
<
KernelContext
>
ctx_
;
std
::
unique_ptr
<
KernelContext
>
ctx_
{
nullptr
}
;
mutable
operators
::
param_t
param_
;
// The corresponding op type.
std
::
string
op_type_
{};
...
...
paddle/fluid/lite/core/lite_tensor.h
浏览文件 @
01e1cdac
...
...
@@ -61,6 +61,14 @@ class TensorLite : public TensorBase<TensorLite> {
TensorLite
()
:
buffer_
(
std
::
make_shared
<
Buffer
>
())
{}
template
<
typename
DType
,
typename
DimT
,
TargetType
Target
>
void
Assign
(
DType
*
data
,
const
DimT
&
dim
)
{
Resize
(
dim
);
auto
*
dst
=
mutable_data
<
DType
>
(
Target
);
CopySync
<
Target
>
(
dst
,
data
,
dim
.
product
()
*
sizeof
(
DType
),
IoDirection
::
HtoD
);
}
template
<
typename
T
>
const
T
*
data
()
const
{
return
static_cast
<
const
T
*>
(
buffer_
->
data
());
...
...
paddle/fluid/lite/core/op_lite.cc
浏览文件 @
01e1cdac
...
...
@@ -28,8 +28,7 @@ std::vector<std::unique_ptr<KernelBase>> OpLite::CreateKernels(
CHECK
(
!
op_type_
.
empty
())
<<
"op_type_ should be set first"
;
auto
pick_kernel
=
[
&
](
const
Place
&
place
)
{
auto
ks
=
KernelRegistry
::
Global
().
Create
(
(
kernel_type
.
empty
()
?
op_type_
:
kernel_type
),
place
.
target
,
auto
ks
=
KernelRegistry
::
Global
().
Create
(
op_type_
,
place
.
target
,
place
.
precision
,
place
.
layout
);
for
(
auto
&&
it
:
ks
)
{
AttachKernel
(
it
.
get
());
...
...
@@ -37,6 +36,15 @@ std::vector<std::unique_ptr<KernelBase>> OpLite::CreateKernels(
}
};
if
(
!
kernel_type
.
empty
())
{
Place
place
;
std
::
string
op_type
,
alias
;
KernelBase
::
ParseKernelType
(
kernel_type
,
&
op_type
,
&
alias
,
&
place
);
pick_kernel
(
place
);
CHECK
(
!
kernels
.
empty
())
<<
"no kernel for kernel type "
<<
kernel_type
;
return
kernels
;
}
std
::
set
<
Place
>
place_set
;
for
(
auto
place
:
places
)
{
place_set
.
insert
(
place
);
...
...
paddle/fluid/lite/core/op_registry.h
浏览文件 @
01e1cdac
...
...
@@ -91,9 +91,9 @@ class KernelRegistry final {
void
Register
(
const
std
::
string
&
name
,
typename
KernelRegistryForTarget
<
Target
,
Precision
,
Layout
>::
creator_t
&&
creator
)
{
VLOG
(
3
)
<<
"register for "
<<
TargetToStr
(
Target
)
<<
":"
<<
PrecisionToStr
(
Precision
)
<<
"//"
<<
GetKernelOffset
<
Target
,
Precision
,
Layout
>
();
//
VLOG(3) << "register for " << TargetToStr(Target) << ":"
//
<< PrecisionToStr(Precision) << "//"
//
<< GetKernelOffset<Target, Precision, Layout>();
using
kernel_registor_t
=
KernelRegistryForTarget
<
Target
,
Precision
,
Layout
>
;
auto
&
varient
=
registries_
[
GetKernelOffset
<
Target
,
Precision
,
Layout
>
()];
...
...
@@ -153,9 +153,6 @@ class KernelRegistor : public lite::Registor<KernelType> {
public:
KernelRegistor
(
const
std
::
string
&
op_type
,
const
std
::
string
&
alias
)
:
Registor
<
KernelType
>
([
=
]
{
VLOG
(
3
)
<<
"Register kernel "
<<
op_type
<<
" for "
<<
TargetToStr
(
target
)
<<
" "
<<
PrecisionToStr
(
precision
)
<<
" "
<<
DataLayoutToStr
(
layout
)
<<
" alias "
<<
alias
;
KernelRegistry
::
Global
().
Register
<
target
,
precision
,
layout
>
(
op_type
,
[
=
]()
->
std
::
unique_ptr
<
KernelType
>
{
std
::
unique_ptr
<
KernelType
>
x
(
new
KernelType
);
...
...
paddle/fluid/lite/core/scope.cc
浏览文件 @
01e1cdac
...
...
@@ -17,7 +17,13 @@
namespace
paddle
{
namespace
lite
{
Scope
::~
Scope
()
{}
Scope
::~
Scope
()
{
for
(
auto
*
x
:
kids_
)
{
if
(
x
)
{
delete
x
;
}
}
}
Scope
&
Scope
::
NewScope
()
const
{
kids_
.
push_back
(
new
Scope
);
...
...
paddle/fluid/lite/core/target_wrapper.h
浏览文件 @
01e1cdac
...
...
@@ -63,7 +63,8 @@ static const std::string& TargetToStr(TargetType target) {
}
static
const
std
::
string
&
PrecisionToStr
(
PrecisionType
precision
)
{
static
const
std
::
string
precision2string
[]
=
{
"unk"
,
"float"
,
"int8"
,
"any"
};
static
const
std
::
string
precision2string
[]
=
{
"unk"
,
"float"
,
"int8_t"
,
"any"
};
auto
x
=
static_cast
<
int
>
(
precision
);
CHECK_LT
(
x
,
static_cast
<
int
>
(
PRECISION
(
NUM
)));
return
precision2string
[
x
];
...
...
@@ -76,6 +77,29 @@ static const std::string& DataLayoutToStr(DataLayoutType layout) {
return
datalayout2string
[
x
];
}
static
const
std
::
string
&
TargetRepr
(
TargetType
target
)
{
static
const
std
::
string
target2string
[]
=
{
"kUnk"
,
"kHost"
,
"kX86"
,
"kCUDA"
,
"kAny"
};
auto
x
=
static_cast
<
int
>
(
target
);
CHECK_LT
(
x
,
static_cast
<
int
>
(
TARGET
(
NUM
)));
return
target2string
[
x
];
}
static
const
std
::
string
&
PrecisionRepr
(
PrecisionType
precision
)
{
static
const
std
::
string
precision2string
[]
=
{
"kUnk"
,
"kFloat"
,
"kInt8"
,
"kAny"
};
auto
x
=
static_cast
<
int
>
(
precision
);
CHECK_LT
(
x
,
static_cast
<
int
>
(
PRECISION
(
NUM
)));
return
precision2string
[
x
];
}
static
const
std
::
string
&
DataLayoutRepr
(
DataLayoutType
layout
)
{
static
const
std
::
string
datalayout2string
[]
=
{
"kUnk"
,
"kNCHW"
,
"kAny"
};
auto
x
=
static_cast
<
int
>
(
layout
);
CHECK_LT
(
x
,
static_cast
<
int
>
(
DATALAYOUT
(
NUM
)));
return
datalayout2string
[
x
];
}
/*
* Place specifies the execution context of a Kernel or input/output for a
* kernel. It is used to make the analysis of the MIR more clear and accurate.
...
...
@@ -228,5 +252,20 @@ class TargetWrapper<TARGET(kCUDA), cudaStream_t, cudaEvent_t> {
};
#endif // LITE_WITH_CUDA
template
<
TargetType
Target
>
void
CopySync
(
void
*
dst
,
void
*
src
,
size_t
size
,
IoDirection
dir
)
{
switch
(
Target
)
{
case
TARGET
(
kX86
):
case
TARGET
(
kHost
):
case
TARGET
(
kARM
):
TargetWrapperX86
::
MemcpySync
(
dst
,
src
,
size
,
IoDirection
::
HtoH
);
break
;
#ifdef LITE_WITH_CUDA
case
TARGET
(
kCUDA
):
TargetWrapperCuda
::
MemcpySync
(
dst
,
src
,
size
,
dir
);
#endif
}
}
}
// namespace lite
}
// namespace paddle
paddle/fluid/lite/core/tensor.h
浏览文件 @
01e1cdac
...
...
@@ -47,7 +47,8 @@ class DDimBase {
DDimBase
()
=
default
;
explicit
DDimBase
(
const
std
::
vector
<
int64_t
>
&
x
)
{
self
()
->
ConstructFrom
(
x
);
}
value_type
operator
[](
int
offset
)
const
{
return
(
*
self
())[
offset
];
}
value_type
operator
[](
int
offset
)
const
{
return
(
*
const_self
())[
offset
];
}
value_type
&
operator
[](
int
offset
)
{
return
(
*
self
())[
offset
];
}
std
::
vector
<
int64_t
>
Vectorize
()
const
{
return
self
()
->
Vectorize
();
}
size_t
size
()
const
{
return
const_self
()
->
size
();
}
bool
empty
()
const
{
return
const_self
()
->
empty
();
}
...
...
@@ -73,18 +74,19 @@ class DDimBase {
{
Slice
(
0
,
col
).
production
(),
Slice
(
col
,
size
()).
production
()}));
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
DDimT
&
dims
)
{
if
(
dims
.
empty
())
{
os
<<
"[]"
;
return
os
;
std
::
string
repr
()
const
{
std
::
stringstream
ss
;
ss
<<
"{"
;
for
(
size_t
i
=
0
;
i
<
this
->
size
()
-
1
;
i
++
)
{
ss
<<
(
*
this
)[
i
]
<<
","
;
}
os
<<
"["
;
for
(
size_t
i
=
0
;
i
<
dims
.
size
()
-
1
;
i
++
)
{
os
<<
dims
[
i
]
<<
" "
;
if
(
!
this
->
empty
())
ss
<<
(
*
this
)[
size
()
-
1
];
ss
<<
"}"
;
return
ss
.
str
();
}
if
(
!
dims
.
empty
())
os
<<
dims
[
dims
.
size
()
-
1
];
os
<<
"]"
;
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
DDimT
&
dims
)
{
os
<<
dims
.
repr
();
return
os
;
}
...
...
@@ -102,6 +104,12 @@ template <typename TensorT>
class
TensorBase
{
public:
TensorBase
()
=
default
;
template
<
typename
T
,
typename
DimT
>
void
Assign
(
T
*
data
,
const
DimT
&
dim
)
{
self
()
->
Assign
(
data
,
dim
);
}
TargetType
target
()
const
{
return
self
()
->
target
();
}
template
<
typename
T
>
...
...
paddle/fluid/lite/core/variable.h
浏览文件 @
01e1cdac
...
...
@@ -24,7 +24,7 @@ namespace lite {
class
Variable
{
public:
template
<
typename
T
>
const
T
&
Get
()
{
const
T
&
Get
()
const
{
return
blob_
.
get
<
T
>
();
}
...
...
paddle/fluid/lite/gen_code/CMakeLists.txt
0 → 100644
浏览文件 @
01e1cdac
lite_cc_library
(
gen_code_lite SRCS gen_code.cc
DEPS program_lite op_lite scope
cpp_op_desc_lite
HVY_DEPS operator
)
lite_cc_library
(
paddle_infer_gencode SRCS paddle_infer.cc DEPS program_lite utils_lite
)
lite_cc_test
(
test_gen_code_lite SRCS gen_code_test.cc DEPS gen_code_lite
${
tensor_lite
}
mul_op_lite
compatible_pb_lite
model_parser_lite
X86_DEPS mul_compute_x86
ARGS --optimized_model=
${
LITE_MODEL_DIR
}
/lite_naive_model_opt SERIAL
)
lite_cc_library
(
__generated_code__
SRCS
${
CMAKE_BINARY_DIR
}
/paddle/fluid/lite/gen_code/__generated_code__.cc
DEPS scope_lite op_lite kernel_lite paddle_infer_gencode
)
lite_cc_test
(
test_generated_code SRCS generated_code_test.cc DEPS __generated_code__
${
ops_lite
}
${
host_kernels
}
X86_DEPS
${
x86_kernels
}
)
add_dependencies
(
__generated_code__ test_gen_code_lite
)
paddle/fluid/lite/gen_code/gen_code.cc
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/fluid/lite/gen_code/gen_code.h"
#include <algorithm>
#include <string>
#include <vector>
namespace
paddle
{
namespace
lite
{
namespace
gencode
{
void
Module
::
AddWeight
(
const
std
::
string
&
name
,
const
TensorRepr
&
tensor
)
{
auto
w_name
=
WeightUniqueName
();
Line
(
string_format
(
"// Create weight: %s"
,
name
.
c_str
()));
// auto* w0 = scope.Var("w0")->GetMutable<lite::Tensor>();
Line
(
string_format
(
"auto* %s = scope->Var(%s)->GetMutable<lite::Tensor>();"
,
w_name
.
c_str
(),
Repr
(
name
).
c_str
()));
// lite::DDim w_ddim({1, 2})
Line
(
string_format
(
"lite::DDim %s_ddim(std::vector<int64_t>(%s));"
,
w_name
.
c_str
(),
tensor
.
ddim
.
repr
().
c_str
()));
// std::vector<float> w_data({});
auto
w_data_repr
=
DataRepr
(
std
::
string
(
static_cast
<
const
char
*>
(
tensor
.
raw_data
),
tensor
.
num_bytes
),
tensor
.
dtype
);
Line
(
string_format
(
"std::vector<%s> %s_data({%s});"
,
PrecisionToStr
(
tensor
.
dtype
).
c_str
(),
w_name
.
c_str
(),
w_data_repr
.
c_str
()));
// w0->Assign<float, lite::DDim, TARGET(kX86)>(w0_data.data(), w0_ddim);
Line
(
string_format
(
"%s->Assign<%s, lite::DDim, TARGET(kX86)>(%s_data.data(), %s_ddim);"
,
w_name
.
c_str
(),
PrecisionToStr
(
tensor
.
dtype
).
c_str
(),
w_name
.
c_str
(),
w_name
.
c_str
()));
Line
(
""
);
}
void
Module
::
AddHeaderIncludeGenCode
()
{
Line
(
""
);
Line
(
"#include <string>"
);
Line
(
"#include <vector>"
);
Line
(
"#include
\"
paddle/fluid/lite/core/compatible_tensor.h
\"
"
);
Line
(
"#include
\"
paddle/fluid/lite/core/context.h
\"
"
);
Line
(
"#include
\"
paddle/fluid/lite/gen_code/paddle_infer.h
\"
"
);
Line
(
"#include
\"
paddle/fluid/lite/core/op_registry.h
\"
"
);
Line
(
"#include
\"
paddle/fluid/lite/core/scope.h
\"
"
);
Line
(
"#include
\"
paddle/fluid/lite/model_parser/cpp/op_desc.h
\"
"
);
Line
(
""
);
Line
(
""
);
}
std
::
string
Module
::
DataRepr
(
const
std
::
string
&
raw_data
,
PrecisionType
dtype
)
{
std
::
stringstream
ss
;
switch
(
dtype
)
{
case
PRECISION
(
kFloat
):
{
const
float
*
raw
=
reinterpret_cast
<
const
float
*>
(
raw_data
.
c_str
());
int
num_elems
=
raw_data
.
size
()
/
sizeof
(
float
);
if
(
num_elems
)
{
for
(
int
i
=
0
;
i
<
num_elems
-
1
;
i
++
)
{
ss
<<
raw
[
i
]
<<
","
;
}
ss
<<
raw
[
num_elems
-
1
];
}
}
break
;
default:
LOG
(
FATAL
)
<<
"Unsupported type "
<<
PrecisionToStr
(
dtype
);
}
return
ss
.
str
();
}
void
Module
::
AddOpDescHelper
(
const
std
::
string
&
op_id
,
const
cpp
::
OpDesc
&
desc
)
{
std
::
string
desc_var
=
op_id
+
"_desc"
;
Line
(
string_format
(
"lite::cpp::OpDesc %s;"
,
desc_var
.
c_str
()));
auto
vec_str_repr
=
[](
const
std
::
vector
<
std
::
string
>
&
vec
)
{
return
Repr
(
vec
);
};
for
(
auto
&
item
:
desc
.
inputs
())
{
Line
(
string_format
(
"%s.SetInput(%s, %s);"
,
desc_var
.
c_str
(),
Repr
(
item
.
first
).
c_str
(),
vec_str_repr
(
item
.
second
).
c_str
()));
}
for
(
auto
&
item
:
desc
.
outputs
())
{
Line
(
string_format
(
"%s.SetOutput(%s, %s);"
,
desc_var
.
c_str
(),
Repr
(
item
.
first
).
c_str
(),
vec_str_repr
(
item
.
second
).
c_str
()));
}
auto
attr_repr
=
[
&
](
const
std
::
string
&
name
)
->
std
::
string
{
using
AttrType
=
OpDescAPI
::
AttrType
;
auto
type
=
desc
.
GetAttrType
(
name
);
switch
(
type
)
{
case
AttrType
::
INT
:
return
std
::
to_string
(
desc
.
GetAttr
<
int
>
(
name
));
case
AttrType
::
FLOAT
:
return
std
::
to_string
(
desc
.
GetAttr
<
float
>
(
name
));
case
AttrType
::
BOOLEAN
:
return
std
::
to_string
(
desc
.
GetAttr
<
bool
>
(
name
));
case
AttrType
::
STRING
:
return
"
\"
"
+
desc
.
GetAttr
<
std
::
string
>
(
name
)
+
"
\"
"
;
case
AttrType
::
STRINGS
:
{
std
::
vector
<
std
::
string
>
tmp
;
auto
vals
=
desc
.
GetAttr
<
std
::
vector
<
std
::
string
>>
(
name
);
std
::
transform
(
vals
.
begin
(),
vals
.
end
(),
std
::
back_inserter
(
tmp
),
[](
const
std
::
string
&
x
)
{
return
Repr
(
x
);
});
return
"{"
+
Join
(
tmp
,
","
)
+
"}"
;
}
default:
LOG
(
FATAL
)
<<
"Unsupported attribute type: "
<<
static_cast
<
int
>
(
type
);
}
return
""
;
};
auto
attr_type_repr
=
[
&
](
const
std
::
string
&
name
)
->
std
::
string
{
using
AttrType
=
OpDescAPI
::
AttrType
;
auto
type
=
desc
.
GetAttrType
(
name
);
switch
(
type
)
{
case
AttrType
::
INT
:
return
"int"
;
case
AttrType
::
FLOAT
:
return
"float"
;
case
AttrType
::
BOOLEAN
:
return
"bool"
;
case
AttrType
::
STRING
:
return
"std::string"
;
case
AttrType
::
STRINGS
:
return
"std::vector<std::string>"
;
default:
LOG
(
FATAL
)
<<
"Unsupported attribute type: "
<<
static_cast
<
int
>
(
type
);
}
return
"unk_t"
;
};
for
(
auto
&
item
:
desc
.
AttrNames
())
{
// Drop the python information.
if
(
item
==
"op_callstack"
)
continue
;
auto
attr_type
=
attr_type_repr
(
item
);
auto
attr_val
=
attr_repr
(
item
);
Line
(
string_format
(
"%s.SetAttr<%s>(%s, %s);"
,
//
desc_var
.
c_str
(),
attr_type
.
c_str
(),
Repr
(
item
).
c_str
(),
attr_val
.
c_str
()));
}
}
void
Module
::
AddOp
(
const
cpp
::
OpDesc
&
op
)
{
auto
op_name
=
OpUniqueName
();
AddOpDescHelper
(
op_name
,
op
);
Line
(
string_format
(
"// Create Op: %s"
,
op
.
Type
().
c_str
()));
Line
(
string_format
(
"auto %s = lite::LiteOpRegistry::Global().Create(
\"
%s
\"
);"
,
op_name
.
c_str
(),
op
.
Type
().
c_str
()));
CHECK
(
op
.
HasAttr
(
kKernelTypeAttr
))
<<
"the kernel type should be specified before generate code."
;
auto
kernel_type
=
op
.
GetAttr
<
std
::
string
>
(
kKernelTypeAttr
);
Line
(
string_format
(
"%s->Attach(%s, exec_scope);"
,
op_name
.
c_str
(),
(
op_name
+
"_desc"
).
c_str
()));
// Create kernel
auto
kernel_name
=
KernelUniqueName
();
Line
(
string_format
(
"auto %s = std::move(%s->CreateKernels(valid_places,
\"
%s
\"
).front());"
,
kernel_name
.
c_str
(),
op_name
.
c_str
(),
kernel_type
.
c_str
()));
// Set Context for kernel
// clang-format off
Line
(
string_format
(
"%s->SetContext(lite::ContextScheduler::Global().NewContext(%s->target()));"
,
kernel_name
.
c_str
(),
kernel_name
.
c_str
()));
// NOLINT
// clang-format on
Line
(
string_format
(
"ops.push_back(%s);"
,
op_name
.
c_str
()));
Line
(
string_format
(
"kernels.push_back(std::move(%s));"
,
kernel_name
.
c_str
()));
op_kinds_
.
insert
(
op
.
Type
());
kernel_kinds_
.
insert
(
kernel_type
);
}
}
// namespace gencode
}
// namespace lite
}
// namespace paddle
paddle/fluid/lite/gen_code/gen_code.h
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <set>
#include <string>
#include <vector>
#include "paddle/fluid/lite/core/compatible_tensor.h"
#include "paddle/fluid/lite/core/framework.pb.h"
#include "paddle/fluid/lite/core/program.h"
#include "paddle/fluid/lite/core/target_wrapper.h"
#include "paddle/fluid/lite/model_parser/cpp/op_desc.h"
#include "paddle/fluid/lite/model_parser/desc_apis.h"
#include "paddle/fluid/lite/utils/string.h"
namespace
paddle
{
namespace
lite
{
namespace
gencode
{
struct
TensorRepr
{
TensorRepr
()
=
default
;
TensorRepr
(
PrecisionType
dtype
,
const
std
::
vector
<
int64_t
>
&
ddim
,
void
*
raw_data
,
size_t
num_bytes
)
:
dtype
(
dtype
),
ddim
(
ddim
),
raw_data
(
raw_data
),
num_bytes
(
num_bytes
)
{}
PrecisionType
dtype
;
lite
::
DDim
ddim
;
const
void
*
raw_data
;
size_t
num_bytes
{};
};
class
Module
{
std
::
vector
<
cpp
::
OpDesc
>
ops
;
std
::
vector
<
TensorRepr
>
weights
;
std
::
vector
<
std
::
string
>
tmp_vars_
;
std
::
stringstream
stream_
;
std
::
set
<
std
::
string
>
kernel_kinds_
;
std
::
set
<
std
::
string
>
op_kinds_
;
int
line_indent_
{};
const
int
indent_unit_
{
2
};
public:
void
NewOp
(
const
cpp
::
OpDesc
&
desc
)
{
ops
.
push_back
(
desc
);
}
void
NewWeight
(
const
TensorRepr
&
x
)
{
weights
.
push_back
(
x
);
}
void
NewTmpVar
(
const
std
::
string
&
x
)
{
tmp_vars_
.
push_back
(
x
);
}
std
::
stringstream
&
stream
()
{
return
stream_
;
}
void
AddHeaderIncludeGenCode
();
void
AddNamespaceBegin
()
{
Line
(
"namespace paddle {"
);
Line
(
"namespace gencode{"
);
Line
(
""
);
}
void
AddNamespaceEnd
()
{
Line
(
""
);
Line
(
"} // namespace gencode"
);
Line
(
"} // namespace paddle"
);
}
void
AddInitFuncBegin
()
{
Line
(
"void PaddlePredictor::Init() {"
);
Line
(
""
);
IncIndent
();
}
void
AddInitFuncEnd
()
{
DecIndent
();
Line
(
""
);
Line
(
"}"
);
}
void
AddScopeDecl
()
{
Line
(
"lite::Scope* scope = static_cast<lite::Scope*>(raw_scope_);"
);
// clang-format off
Line
(
"lite::Scope* exec_scope = static_cast<lite::Scope*>(raw_exe_scope_);"
);
// NOLINT
// clang-format on
// Create feed and fetch in exec_scope.
Line
(
string_format
(
"exec_scope->Var(%s);"
,
Repr
(
"feed"
).
c_str
()));
Line
(
string_format
(
"exec_scope->Var(%s);"
,
Repr
(
"fetch"
).
c_str
()));
}
void
AddValidPlaceDecl
()
{
// clang-format off
Line
(
"std::vector<lite::Place> valid_places({lite::Place({TARGET(kX86), PRECISION(kFloat), DATALAYOUT(kNCHW)}), lite::Place({TARGET(kHost), PRECISION(kAny), DATALAYOUT(kAny)})});"
);
// NOLINT
// clang-format on
}
void
AddMemberCast
()
{
Line
(
"// Cast the raw members"
);
// clang-format off
Line
(
string_format
(
"auto& ops = *static_cast<std::vector<std::shared_ptr<lite::OpLite>>*>(raw_ops_);"
));
// NOLINT
Line
(
string_format
(
"auto& kernels = *static_cast<std::vector<std::unique_ptr<lite::KernelBase>>*>(raw_kernels_);"
));
// NOLINT
// clang-format on
Line
(
""
);
}
void
AddWeight
(
const
std
::
string
&
name
,
const
TensorRepr
&
tensor
);
void
AddTmpVar
(
const
std
::
string
&
x
)
{
Line
(
string_format
(
"// Create temporary variable: %s"
,
x
.
c_str
()));
Line
(
string_format
(
"exec_scope->Var(%s);"
,
Repr
(
x
).
c_str
()));
Line
(
""
);
}
void
AddOp
(
const
cpp
::
OpDesc
&
op
);
void
AddOpDescHelper
(
const
std
::
string
&
op_id
,
const
cpp
::
OpDesc
&
desc
);
void
AddOpCompileDeps
()
{
Line
(
""
);
Line
(
"// Add Operator compile deps"
);
for
(
auto
&
op_type
:
op_kinds_
)
{
Line
(
string_format
(
"USE_LITE_OP(%s)"
,
op_type
.
c_str
()));
}
Line
(
""
);
}
void
AddKernelCompileDeps
()
{
Line
(
"// Add Kernel compile deps"
);
std
::
string
op_type
,
alias
;
Place
place
;
for
(
auto
&
kernel_type
:
kernel_kinds_
)
{
KernelBase
::
ParseKernelType
(
kernel_type
,
&
op_type
,
&
alias
,
&
place
);
Line
(
string_format
(
"USE_LITE_KERNEL(%s, %s, %s, %s, %s)"
,
//
op_type
.
c_str
(),
//
TargetRepr
(
place
.
target
).
c_str
(),
PrecisionRepr
(
place
.
precision
).
c_str
(),
DataLayoutRepr
(
place
.
layout
).
c_str
(),
alias
.
c_str
()));
}
}
private:
std
::
string
WeightUniqueName
()
const
{
return
"w_"
+
std
::
to_string
(
weight_counter_
++
);
}
std
::
string
TmpVarUniqueName
()
const
{
return
"tmp_"
+
std
::
to_string
(
tmp_var_counter_
++
);
}
std
::
string
OpUniqueName
()
const
{
return
"op_"
+
std
::
to_string
(
op_counter_
++
);
}
std
::
string
KernelUniqueName
()
const
{
return
"kernel_"
+
std
::
to_string
(
kernel_counter_
++
);
}
std
::
string
DataRepr
(
const
std
::
string
&
raw_data
,
PrecisionType
dtype
);
void
IncIndent
()
{
line_indent_
++
;
}
void
DecIndent
()
{
line_indent_
--
;
}
void
Line
(
const
std
::
string
&
x
)
{
std
::
string
indent_str
(
line_indent_
*
indent_unit_
,
' '
);
stream
()
<<
indent_str
<<
x
<<
"
\n
"
;
}
private:
mutable
int
weight_counter_
{};
mutable
int
tmp_var_counter_
{};
mutable
int
op_counter_
{};
mutable
int
kernel_counter_
{};
};
class
ProgramCodeGenerator
{
public:
ProgramCodeGenerator
(
const
framework
::
proto
::
ProgramDesc
&
program
,
const
lite
::
Scope
&
exec_scope
)
:
program_
(
program
),
exec_scope_
(
exec_scope
)
{
LOG
(
INFO
)
<<
program
.
DebugString
();
}
std
::
string
GenCode
()
{
Module
m
;
m
.
AddHeaderIncludeGenCode
();
m
.
AddNamespaceBegin
();
m
.
AddInitFuncBegin
();
m
.
AddMemberCast
();
m
.
AddScopeDecl
();
m
.
AddValidPlaceDecl
();
AddWeights
(
&
m
);
AddTmpVars
(
&
m
);
AddOps
(
&
m
);
m
.
AddInitFuncEnd
();
m
.
AddNamespaceEnd
();
m
.
AddOpCompileDeps
();
m
.
AddKernelCompileDeps
();
return
m
.
stream
().
str
();
}
void
AddWeights
(
Module
*
m
)
{
for
(
auto
&
var
:
program_
.
blocks
(
0
).
vars
())
{
if
(
var
.
persistable
())
{
auto
name
=
var
.
name
();
if
(
name
==
"feed"
||
name
==
"fetch"
)
continue
;
const
auto
&
tensor
=
exec_scope_
.
FindVar
(
name
)
->
Get
<
lite
::
Tensor
>
();
TensorRepr
repr
;
TensorToRepr
(
tensor
,
&
repr
);
m
->
AddWeight
(
name
,
repr
);
}
}
}
void
AddTmpVars
(
Module
*
m
)
{
for
(
auto
&
var
:
program_
.
blocks
(
0
).
vars
())
{
if
(
!
var
.
persistable
())
{
m
->
AddTmpVar
(
var
.
name
());
}
}
}
void
AddOps
(
Module
*
m
)
{
for
(
auto
&
op
:
program_
.
blocks
(
0
).
ops
())
{
pb
::
OpDesc
pb_desc
(
op
);
cpp
::
OpDesc
cpp_desc
;
TransformOpDescPbToCpp
(
pb_desc
,
&
cpp_desc
);
m
->
AddOp
(
cpp_desc
);
}
}
private:
void
TensorToRepr
(
const
lite
::
Tensor
&
tensor
,
TensorRepr
*
repr
)
{
repr
->
ddim
=
tensor
.
dims
();
// TODO(Superjomn) support other types.
repr
->
dtype
=
PRECISION
(
kFloat
);
repr
->
raw_data
=
tensor
.
data
<
float
>
();
repr
->
num_bytes
=
repr
->
ddim
.
production
()
*
sizeof
(
float
);
}
private:
const
framework
::
proto
::
ProgramDesc
&
program_
;
const
lite
::
Scope
&
exec_scope_
;
};
}
// namespace gencode
}
// namespace lite
}
// namespace paddle
paddle/fluid/lite/gen_code/gen_code_test.cc
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/fluid/lite/gen_code/gen_code.h"
#include <gflags/gflags.h>
#include <gtest/gtest.h>
#include <fstream>
#include <string>
#include <utility>
#include <vector>
#include "paddle/fluid/lite/core/compatible_tensor.h"
#include "paddle/fluid/lite/core/context.h"
#include "paddle/fluid/lite/core/op_registry.h"
#include "paddle/fluid/lite/core/scope.h"
#include "paddle/fluid/lite/model_parser/cpp/op_desc.h"
#include "paddle/fluid/lite/model_parser/model_parser.h"
DEFINE_string
(
optimized_model
,
""
,
""
);
DEFINE_string
(
generated_code_file
,
"__generated_code__.cc"
,
""
);
namespace
paddle
{
namespace
lite
{
namespace
gencode
{
// Manually construct a program.
TEST
(
gen_code
,
manual
)
{
// For holding the weights.
lite
::
Scope
scope
;
// For holding the temporary variables.
auto
&
tmp_scope
=
scope
.
NewScope
();
// Create weight variables.
auto
*
w0
=
scope
.
Var
(
"w0"
)
->
GetMutable
<
lite
::
Tensor
>
();
// Create temporary variables.
auto
*
a
=
tmp_scope
.
Var
(
"x"
)
->
GetMutable
<
lite
::
Tensor
>
();
tmp_scope
.
Var
(
"out"
)
->
GetMutable
<
lite
::
Tensor
>
();
// Set weights.
std
::
vector
<
float
>
w0_data
({
0
,
1
,
2
,
3
});
w0
->
Assign
<
float
,
lite
::
DDim
,
TARGET
(
kX86
)
>
(
w0_data
.
data
(),
lite
::
DDim
{
std
::
vector
<
int64_t
>
({
2
,
2
})});
std
::
vector
<
float
>
a_data
({
0
,
1
,
2
,
3
});
a
->
Assign
<
float
,
lite
::
DDim
,
TARGET
(
kX86
)
>
(
a_data
.
data
(),
lite
::
DDim
{
std
::
vector
<
int64_t
>
({
2
,
2
})});
std
::
vector
<
Place
>
valid_places
({
Place
{
TARGET
(
kX86
),
PRECISION
(
kFloat
)},
Place
{
TARGET
(
kHost
),
PRECISION
(
kFloat
)},
Place
{
TARGET
(
kHost
),
PRECISION
(
kAny
)},
});
auto
mul_op
=
LiteOpRegistry
::
Global
().
Create
(
"mul"
);
cpp
::
OpDesc
mul_op_desc
;
mul_op_desc
.
SetType
(
"mul"
);
mul_op_desc
.
SetInput
(
"X"
,
{
"x"
});
mul_op_desc
.
SetInput
(
"Y"
,
{
"w0"
});
mul_op_desc
.
SetAttr
(
"x_num_col_dims"
,
1
);
mul_op_desc
.
SetAttr
(
"y_num_col_dims"
,
1
);
mul_op_desc
.
SetOutput
(
"Out"
,
{
"out"
});
mul_op
->
Attach
(
mul_op_desc
,
&
tmp_scope
);
auto
mul_kernel
=
std
::
move
(
mul_op
->
CreateKernels
(
valid_places
).
front
());
auto
fc_ctx
=
ContextScheduler
::
Global
().
NewContext
(
TARGET
(
kX86
));
mul_op
->
CheckShape
();
mul_op
->
InferShape
();
mul_kernel
->
SetContext
(
std
::
move
(
fc_ctx
));
mul_kernel
->
Launch
();
}
TEST
(
gen_code
,
auto_gen
)
{
std
::
vector
<
float
>
w0_data
({
0
,
1
,
2
,
3
});
TensorRepr
w0
(
PRECISION
(
kFloat
),
std
::
vector
<
int64_t
>
({
2
,
2
}),
w0_data
.
data
(),
w0_data
.
size
()
*
sizeof
(
float
));
std
::
vector
<
float
>
w1_data
({
0.01
,
1.2
,
2.3
,
3.4
,
1.1
,
2.2
});
TensorRepr
w1
(
PRECISION
(
kFloat
),
std
::
vector
<
int64_t
>
({
3
,
2
}),
w1_data
.
data
(),
w1_data
.
size
()
*
sizeof
(
float
));
cpp
::
OpDesc
op0
;
op0
.
SetType
(
"mul"
);
op0
.
SetInput
(
"X"
,
{
"a"
,
"b"
});
op0
.
SetOutput
(
"Out"
,
{
"out0"
});
op0
.
SetAttr
<
std
::
string
>
(
"desc"
,
"this is a desc"
);
op0
.
SetAttr
<
int
>
(
"x_col"
,
1
);
op0
.
SetAttr
<
int
>
(
"y_col"
,
2
);
op0
.
SetAttr
<
std
::
string
>
(
kKernelTypeAttr
,
"x86"
);
gencode
::
Module
module
;
module
.
AddHeaderIncludeGenCode
();
module
.
AddNamespaceBegin
();
module
.
AddInitFuncBegin
();
module
.
AddMemberCast
();
module
.
AddWeight
(
"w0"
,
w0
);
module
.
AddWeight
(
"w1"
,
w1
);
module
.
AddTmpVar
(
"a"
);
module
.
AddTmpVar
(
"b"
);
module
.
AddOp
(
op0
);
module
.
AddInitFuncEnd
();
module
.
AddNamespaceEnd
();
LOG
(
INFO
)
<<
module
.
stream
().
str
();
}
TEST
(
gen_code
,
optimized_program
)
{
lite
::
Scope
scope
;
framework
::
proto
::
ProgramDesc
desc
;
LoadModel
(
FLAGS_optimized_model
,
&
scope
,
&
desc
);
ProgramCodeGenerator
codegen
(
desc
,
scope
);
std
::
ofstream
file
(
FLAGS_generated_code_file
);
file
<<
codegen
.
GenCode
();
file
.
close
();
}
}
// namespace gencode
}
// namespace lite
}
// namespace paddle
USE_LITE_OP
(
mul
);
USE_LITE_KERNEL
(
mul
,
kX86
,
kFloat
,
kNCHW
,
def
);
paddle/fluid/lite/gen_code/generated_code_test.cc
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/fluid/lite/gen_code/paddle_infer.h"
namespace
paddle
{
namespace
lite
{
TEST
(
PaddlePredictor
,
Init
)
{
gencode
::
PaddlePredictor
predictor
;
predictor
.
Init
();
}
TEST
(
PaddlePredictor
,
Run
)
{
gencode
::
PaddlePredictor
predictor
;
predictor
.
Init
();
LOG
(
INFO
)
<<
"run the generated code"
;
auto
input_tensor
=
predictor
.
GetInput
(
0
);
input_tensor
->
Resize
(
std
::
vector
<
int64_t
>
({
100
,
100
}));
auto
*
data
=
input_tensor
->
mutable_data
<
float
>
();
for
(
int
i
=
0
;
i
<
100
*
100
;
i
++
)
{
data
[
i
]
=
i
;
}
predictor
.
Run
();
auto
output_tensor
=
predictor
.
GetOutput
(
0
);
LOG
(
INFO
)
<<
"output: "
<<
output_tensor
->
data
<
float
>
()[
0
];
}
}
// namespace lite
}
// namespace paddle
paddle/fluid/lite/gen_code/paddle_infer.cc
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/fluid/lite/gen_code/paddle_infer.h"
#include "paddle/fluid/lite/core/compatible_tensor.h"
#include "paddle/fluid/lite/core/op_lite.h"
namespace
paddle
{
namespace
gencode
{
void
Tensor
::
Resize
(
const
Tensor
::
ddim_t
&
shape
)
{
CHECK
(
raw_mutable_tensor_
);
auto
*
tensor
=
static_cast
<
lite
::
Tensor
*>
(
raw_mutable_tensor_
);
tensor
->
Resize
(
shape
);
}
#define FOR_EACH_TYPE(HANDLE) \
HANDLE(int); \
HANDLE(float); \
HANDLE(int8_t); \
HANDLE(int64_t);
#define IMPL_DATA(T) \
template <> \
const T *Tensor::data<T>() const { \
CHECK(raw_tensor_); \
const auto *tensor = static_cast<const lite::Tensor *>(raw_tensor_); \
return tensor->data<T>(); \
}
FOR_EACH_TYPE
(
IMPL_DATA
);
#undef IMPL_DATA
#define IMPL_MUTABLE_DATA(T) \
template <> \
T *Tensor::mutable_data<T>() { \
CHECK(raw_mutable_tensor_); \
auto *tensor = static_cast<lite::Tensor *>(raw_mutable_tensor_); \
return tensor->mutable_data<T>(); \
}
FOR_EACH_TYPE
(
IMPL_MUTABLE_DATA
);
#undef IMPL_MUTABLE_DATA
PaddlePredictor
::
PaddlePredictor
()
{
raw_ops_
=
new
std
::
vector
<
std
::
shared_ptr
<
lite
::
OpLite
>>
;
raw_kernels_
=
new
std
::
vector
<
std
::
unique_ptr
<
lite
::
KernelBase
>>
;
raw_scope_
=
new
lite
::
Scope
;
raw_exe_scope_
=
&
(
static_cast
<
lite
::
Scope
*>
(
raw_scope_
)
->
NewScope
());
}
std
::
unique_ptr
<
Tensor
>
PaddlePredictor
::
GetTensor
(
const
std
::
string
&
id
)
const
{
auto
*
exe_scope
=
static_cast
<
lite
::
Scope
*>
(
raw_exe_scope_
);
const
auto
*
var
=
exe_scope
->
FindVar
(
id
);
const
auto
&
tensor
=
var
->
Get
<
lite
::
Tensor
>
();
return
std
::
unique_ptr
<
Tensor
>
(
new
Tensor
(
&
tensor
,
nullptr
));
}
std
::
unique_ptr
<
Tensor
>
PaddlePredictor
::
GetMutableTensor
(
const
std
::
string
&
id
)
{
auto
*
exe_scope
=
static_cast
<
lite
::
Scope
*>
(
raw_exe_scope_
);
auto
*
var
=
exe_scope
->
FindVar
(
id
);
auto
*
tensor
=
var
->
GetMutable
<
lite
::
Tensor
>
();
return
std
::
unique_ptr
<
Tensor
>
(
new
Tensor
(
nullptr
,
tensor
));
}
#define CAST_OPS \
auto *ops = \
static_cast<std::vector<std::shared_ptr<lite::OpLite>> *>(raw_ops_);
#define CAST_KERNELS \
auto *kernels = \
static_cast<std::vector<std::unique_ptr<lite::KernelBase>> *>( \
raw_kernels_);
#define CAST_SCOPE auto *scope = static_cast<lite::Scope *>(raw_scope_);
PaddlePredictor
::~
PaddlePredictor
()
{
CAST_OPS
CAST_KERNELS
CAST_SCOPE
if
(
ops
)
{
delete
ops
;
}
if
(
kernels
)
{
delete
kernels
;
}
if
(
scope
)
{
delete
scope
;
}
}
void
PaddlePredictor
::
Run
()
{
CAST_OPS
CAST_KERNELS
CHECK
(
ops
);
CHECK
(
kernels
);
CHECK_EQ
(
ops
->
size
(),
kernels
->
size
());
for
(
size_t
i
=
0
;
i
<
ops
->
size
();
i
++
)
{
LOG
(
INFO
)
<<
"Running the "
<<
i
<<
"-th operator"
;
ops
->
at
(
i
)
->
InferShape
();
kernels
->
at
(
i
)
->
Launch
();
}
}
std
::
unique_ptr
<
Tensor
>
PaddlePredictor
::
GetInput
(
size_t
offset
)
{
auto
*
exec_scope
=
static_cast
<
lite
::
Scope
*>
(
raw_exe_scope_
);
auto
*
_feed_list
=
exec_scope
->
FindVar
(
"feed"
);
CHECK
(
_feed_list
)
<<
"no feed variable in exec_scope"
;
auto
*
feed_list
=
_feed_list
->
GetMutable
<
std
::
vector
<
lite
::
Tensor
>>
();
if
(
offset
>=
feed_list
->
size
())
{
feed_list
->
resize
(
offset
+
1
);
}
return
std
::
unique_ptr
<
Tensor
>
(
new
Tensor
(
nullptr
,
&
feed_list
->
at
(
offset
)));
}
std
::
unique_ptr
<
Tensor
>
PaddlePredictor
::
GetOutput
(
size_t
offset
)
{
auto
*
exec_scope
=
static_cast
<
lite
::
Scope
*>
(
raw_exe_scope_
);
auto
*
_fetch_list
=
exec_scope
->
FindVar
(
"fetch"
);
CHECK
(
_fetch_list
)
<<
"no fatch variable in exec_scope"
;
auto
&
fetch_list
=
*
_fetch_list
->
GetMutable
<
std
::
vector
<
lite
::
Tensor
>>
();
CHECK_LT
(
offset
,
fetch_list
.
size
())
<<
"offset "
<<
offset
<<
" overflow"
;
return
std
::
unique_ptr
<
Tensor
>
(
new
Tensor
(
&
fetch_list
.
at
(
offset
),
nullptr
));
}
}
// namespace gencode
}
// namespace paddle
paddle/fluid/lite/gen_code/paddle_infer.h
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <memory>
#include <string>
#include <vector>
namespace
paddle
{
namespace
gencode
{
/// Zero Copy Tensor.
class
Tensor
{
public:
using
ddim_t
=
std
::
vector
<
int64_t
>
;
Tensor
(
const
void
*
raw_tensor
,
void
*
raw_mutable_tensor
)
:
raw_tensor_
(
raw_tensor
),
raw_mutable_tensor_
(
raw_mutable_tensor
)
{}
void
Resize
(
const
ddim_t
&
shape
);
template
<
typename
T
>
const
T
*
data
()
const
;
template
<
typename
T
>
T
*
mutable_data
();
private:
const
void
*
raw_tensor_
;
void
*
raw_mutable_tensor_
{};
};
/*
* Predictor for the generated code.
*/
class
PaddlePredictor
{
public:
void
Init
();
std
::
unique_ptr
<
Tensor
>
GetTensor
(
const
std
::
string
&
id
)
const
;
std
::
unique_ptr
<
Tensor
>
GetMutableTensor
(
const
std
::
string
&
id
);
// Get offset-th col of feed.
std
::
unique_ptr
<
Tensor
>
GetInput
(
size_t
offset
);
std
::
unique_ptr
<
Tensor
>
GetOutput
(
size_t
offset
);
void
Run
();
PaddlePredictor
();
~
PaddlePredictor
();
private:
void
*
raw_ops_
;
void
*
raw_kernels_
;
void
*
raw_scope_
{};
void
*
raw_exe_scope_
{};
// raw_exe_scope is not owned.
};
}
// namespace gencode
}
// namespace paddle
paddle/fluid/lite/kernels/x86/CMakeLists.txt
浏览文件 @
01e1cdac
paddle/fluid/lite/model_parser/cpp/op_desc.cc
浏览文件 @
01e1cdac
...
...
@@ -14,6 +14,7 @@
#include "paddle/fluid/lite/model_parser/cpp/op_desc.h"
#include <set>
#include <utility>
namespace
paddle
{
namespace
lite
{
...
...
@@ -48,7 +49,8 @@ FindAttr(const cpp::OpDesc& desc, const std::string& name) {
template <> \
T OpDesc::GetAttr<T>(const std::string& name) const { \
auto pair = FindAttr(*this, name); \
CHECK(pair.second->second == AttrType::repr__); \
CHECK(pair.second->second == AttrType::repr__) \
<< "required type is " << #repr__ << " not match the true type"; \
return pair.first->second.get<T>(); \
}
...
...
paddle/fluid/lite/model_parser/pb/op_desc.cc
浏览文件 @
01e1cdac
...
...
@@ -44,7 +44,7 @@ FindAttr(framework::proto::OpDesc *desc, const std::string &name) {
}
SET_IMPL_ONE
(
int
,
INT
,
i
);
SET_IMPL_ONE
(
float
,
FLOAT
,
f
);
SET_IMPL_ONE
(
bool
,
FLOAT
,
f
);
SET_IMPL_ONE
(
bool
,
BOOLEAN
,
b
);
template
<
>
void
OpDesc
::
SetAttr
<
std
::
vector
<
int
>>
(
const
std
::
string
&
name
,
...
...
paddle/fluid/lite/operators/feed_op.cc
浏览文件 @
01e1cdac
...
...
@@ -38,8 +38,8 @@ class FeedOp : public OpLite {
auto
feed_var_name
=
opdesc
.
Input
(
"X"
).
front
();
auto
*
feed_var
=
scope
->
FindVar
(
feed_var_name
);
CHECK
(
feed_var
);
auto
&
feed_tensor_list
=
feed_var
->
Get
<
std
::
vector
<
lite
::
Tensor
>>
();
param_
.
feed_list
=
&
feed_tensor_list
;
auto
*
feed_tensor_list
=
feed_var
->
GetMutable
<
std
::
vector
<
lite
::
Tensor
>>
();
param_
.
feed_list
=
feed_tensor_list
;
auto
out_name
=
opdesc
.
Output
(
"Out"
).
front
();
auto
*
out_var
=
scope
->
FindVar
(
out_name
);
...
...
paddle/fluid/lite/operators/mul_op.h
浏览文件 @
01e1cdac
...
...
@@ -45,10 +45,11 @@ class MulOpLite : public OpLite {
CHECK
(
var
);
param_
.
x
=
var
->
GetMutable
<
Tensor
>
();
var
=
scope
->
FindVar
(
W
);
CHECK
(
var
);
CHECK
(
var
)
<<
"no var called "
<<
W
;
param_
.
y
=
var
->
GetMutable
<
Tensor
>
();
CHECK
(
scope
->
FindVar
(
out
));
param_
.
output
=
scope
->
FindVar
(
out
)
->
GetMutable
<
Tensor
>
();
var
=
scope
->
FindVar
(
out
);
CHECK
(
var
)
<<
"no var called "
<<
out
;
param_
.
output
=
var
->
GetMutable
<
Tensor
>
();
param_
.
x_num_col_dims
=
op_desc
.
GetAttr
<
int
>
(
"x_num_col_dims"
);
param_
.
y_num_col_dims
=
op_desc
.
GetAttr
<
int
>
(
"y_num_col_dims"
);
...
...
paddle/fluid/lite/tools/build.sh
浏览文件 @
01e1cdac
...
...
@@ -4,15 +4,26 @@ set -ex
TESTS_FILE
=
"./lite_tests.txt"
readonly
common_flags
=
"-DWITH_LITE=ON -DLITE_WITH_LIGHT_WEIGHT_FRAMEWORK=OFF -DWITH_PYTHON=OFF -DWITH_TESTING=ON -DLITE_WITH_ARM=OFF"
# for code gen, a source file is generated after a test, but is dependended by some targets in cmake.
# here we fake an empty file to make cmake works.
function
prepare_for_codegen
{
# in build directory
mkdir
-p
./paddle/fluid/lite/gen_code
touch
./paddle/fluid/lite/gen_code/__generated_code__.cc
}
function
cmake_x86
{
prepare_for_codegen
cmake ..
-DWITH_GPU
=
OFF
-DWITH_MKLDNN
=
OFF
-DLITE_WITH_X86
=
ON
${
common_flags
}
}
function
cmake_x86_for_CI
{
prepare_for_codegen
cmake ..
-DWITH_GPU
=
OFF
-DWITH_MKLDNN
=
OFF
-DLITE_WITH_X86
=
ON
${
common_flags
}
-DLITE_WITH_PROFILE
=
ON
}
function
cmake_gpu
{
prepare_for_codegen
cmake ..
" -DWITH_GPU=ON {common_flags} -DLITE_WITH_GPU=ON"
}
...
...
@@ -31,18 +42,19 @@ function cmake_arm {
-DARM_TARGET_OS
=
$1
-DARM_TARGET_ARCH_ABI
=
$2
}
function
build
{
file
=
$1
for
_test
in
$(
cat
$file
)
;
do
make
$_test
-j
$(
expr
$(
nproc
)
- 2
)
done
}
#
function build {
#
file=$1
#
for _test in $(cat $file); do
#
make $_test -j$(expr $(nproc) - 2)
#
done
#
}
# It will eagerly test all lite related unittests.
function
test_lite
{
local
file
=
$1
echo
"file:
${
file
}
"
for
_test
in
$(
cat
$file
)
;
do
make
$_test
-j
$(
expr
$(
nproc
)
- 2
)
ctest
-R
$_test
-V
done
}
...
...
@@ -86,7 +98,7 @@ function build_test_server {
cd
./build
export
LD_LIBRARY_PATH
=
"
$LD_LIBRARY_PATH
:/paddle/build/third_party/install/mklml/lib"
cmake_x86_for_CI
build
$TESTS_FILE
#
build $TESTS_FILE
test_lite
$TESTS_FILE
}
...
...
@@ -165,10 +177,10 @@ function main {
TESTS_FILE
=
"
${
i
#*=
}
"
shift
;;
build
)
build
$TESTS_FILE
shift
;;
#
build)
#
build $TESTS_FILE
#
shift
#
;;
cmake_x86
)
cmake_x86
shift
...
...
paddle/fluid/lite/utils/CMakeLists.txt
浏览文件 @
01e1cdac
...
...
@@ -8,4 +8,4 @@ set(utils_DEPS glog)
lite_cc_test
(
test_varient SRCS varient_test.cc DEPS utils_lite
)
cc_library
(
any_lite SRCS any.cc
)
cc_library
(
utils_lite SRCS cp_logging.cc DEPS
${
utils_DEPS
}
any_lite
)
cc_library
(
utils_lite SRCS cp_logging.cc
string.cc
DEPS
${
utils_DEPS
}
any_lite
)
paddle/fluid/lite/utils/string.cc
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/fluid/lite/utils/string.h"
namespace
paddle
{
namespace
lite
{}
// namespace lite
}
// namespace paddle
paddle/fluid/lite/utils/string.h
0 → 100644
浏览文件 @
01e1cdac
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdarg.h> // For va_start, etc.
#include <algorithm>
#include <cstring>
#include <memory> // For std::unique_ptr
#include <sstream>
#include <string>
#include <vector>
namespace
paddle
{
namespace
lite
{
static
std
::
string
string_format
(
const
std
::
string
fmt_str
,
...)
{
/* Reserve two times as much as the length of the fmt_str */
int
final_n
,
n
=
(
static_cast
<
int
>
(
fmt_str
.
size
()))
*
2
;
std
::
unique_ptr
<
char
[]
>
formatted
;
va_list
ap
;
while
(
1
)
{
formatted
.
reset
(
new
char
[
n
]);
/* Wrap the plain char array into the unique_ptr */
std
::
strcpy
(
&
formatted
[
0
],
fmt_str
.
c_str
());
// NOLINT
va_start
(
ap
,
fmt_str
);
final_n
=
vsnprintf
(
&
formatted
[
0
],
n
,
fmt_str
.
c_str
(),
ap
);
va_end
(
ap
);
if
(
final_n
<
0
||
final_n
>=
n
)
n
+=
abs
(
final_n
-
n
+
1
);
else
break
;
}
return
std
::
string
(
formatted
.
get
());
}
template
<
typename
T
>
static
std
::
string
to_string_with_precision
(
const
T
&
v
,
const
int
n
=
6
)
{
std
::
stringstream
ss
;
ss
.
precision
(
n
);
ss
<<
std
::
fixed
<<
v
;
return
ss
.
str
();
}
static
std
::
string
Join
(
const
std
::
vector
<
std
::
string
>&
vec
,
const
std
::
string
&
delim
)
{
if
(
vec
.
empty
())
return
""
;
std
::
stringstream
ss
;
for
(
size_t
i
=
0
;
i
<
vec
.
size
()
-
1
;
i
++
)
ss
<<
vec
[
i
]
<<
delim
;
if
(
!
vec
.
empty
())
{
ss
<<
vec
.
back
();
}
return
ss
.
str
();
}
static
std
::
string
Repr
(
const
std
::
string
&
x
)
{
return
"
\"
"
+
x
+
"
\"
"
;
}
static
std
::
string
Repr
(
const
std
::
vector
<
std
::
string
>&
v
)
{
std
::
vector
<
std
::
string
>
tmp
;
std
::
transform
(
v
.
begin
(),
v
.
end
(),
std
::
back_inserter
(
tmp
),
[](
const
std
::
string
&
x
)
{
return
Repr
(
x
);
});
return
"{"
+
Join
(
tmp
,
","
)
+
"}"
;
}
}
// namespace lite
}
// namespace paddle
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录