-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add piano graph executor #36
add piano graph executor #36
Conversation
…o add_piano_graph_executor
} | ||
|
||
template <framework::proto::VarType::Type T> | ||
constexpr note::ElementTypeProto VarType2NoteType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个模板函数有在哪里用到吗
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
暂时并没有用到。。。
namespace paddle { | ||
namespace piano { | ||
|
||
TEST(GraphExecutorTest, basic) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
符号执行的子步骤单测需要测下吗
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这些子步骤都写在了.cc文件里,单独拎出来单测有点麻烦。。。目前拓扑排序和RunCompile
我是通过Compile
函数里往GetCompileOrder
添加op_type
来测试的,这方面可以完善下。CreateInputOperand
是通过ModuleProto
的值来判断,这个了解不多,应该也能完善
in_ops.emplace(n, std::unordered_set<Node*>()); | ||
out_ops.emplace(n, std::unordered_set<Node*>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
为什么拓扑排序要写的如此麻烦,不能使用一个std::vector<Node*, size_t>维护入度吗?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不能啊。由于op Node
的inputs
是var Node
,而不同var Node
的inputs
可能会有重叠,如果用std::vector<Node*, size_t>
的话,这重叠的op Node
就被重复计算,但后面topo遍历时却只会减一次。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
形象点说就是这样:
op1 op2
| / |
var1 var2
\ /
op3
如果用vector
,计算op3
的入度时,op2
会被统计两次。但topo遍历时,op2
只遍历了一次,op3
的入度也就只减了一次。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我的理解,即使你说的这种case,下面这种写法也是正确的。
void TopologicSortGraph(const GraphNodeVec& cluster,
GraphNodeVec* cluster_sorted) {
std::unordered_set<Node*> cluster_set(cluster.cbegin(), cluster.cend());
std::unordered_map<Node*, std::vector<Node*>> adj_list;
std::unordered_map<Node*, size_t> in_degree;
std::queue<Node*> queue;
for (auto* n : cluster) {
PADDLE_ENFORCE_EQ(n->IsOp(), true,
platform::errors::InvalidArgument(
"Cluster Sub-Graph all should be op"));
// the op's input is var
for (auto* in_var : n->inputs) {
// the var's input is op
for (auto* in_op : in_var->inputs) {
if (cluster_set.count(in_op) != 0) {
adj_list[in_op].emplace_back(n);
in_degree[n]++;
}
}
}
}
// find topology entries
for (auto* n : cluster) {
if (!in_degree[n]) {
queue.push(n);
}
}
// topological sorting
while (!queue.empty()) {
auto* cur_op = queue.front();
queue.pop();
cluster_sorted->emplace_back(cur_op);
for (auto* adj : adj_list[cur_op]) {
in_degree[adj]--;
if (!in_degree[adj]) {
queue.push(adj);
}
}
}
PADDLE_ENFORCE_EQ(cluster_sorted.size(), cluster.size(),
platform::errors::PreconditionNotMet(
"Cluster Sub-Graph shouldn't contain cycle."));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这样写的确可以哈,就是adj_list
会有重复node。但在重复结点数目不多的情况下,相比unordered_set
耗时会短点,我改下
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
将std::unordered_map<Node*, std::unordered_set<Node*>> out_ops;
替换为std::unordered_map<Node*, size_t>
多数情况下也能减少空间吧,另外,重复node出现的概率不会太高且重复的次数一般也较少。这样的代码可读性个人感觉好一些。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
已修改~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果想去重的话,可以试试下面的写法:
void TopologicSortGraph(const GraphNodeVec& cluster,
GraphNodeVec* cluster_sorted) {
std::unordered_set<Node*> cluster_set(cluster.cbegin(), cluster.cend());
std::unordered_map<Node*, std::unordered_map<Node*, size_t>> adj_list;
std::unordered_map<Node*, size_t> indegree;
std::queue<Node*> queue;
for (auto* n : cluster) {
PADDLE_ENFORCE_EQ(n->IsOp(), true,
platform::errors::InvalidArgument(
"Cluster Sub-Graph all should be op"));
// the op's input is var
for (auto* in_var : n->inputs) {
// the var's input is op
for (auto* in_op : in_var->inputs) {
if (cluster_set.count(in_op) != 0) {
++adj_list[in_op][n];
++indegree[n];
}
}
}
}
// find topology entries
for (auto* n : cluster) {
if (!indegree[n]) {
queue.push(n);
}
}
// topological sorting
while (!queue.empty()) {
auto* cur_op = queue.front();
queue.pop();
cluster_sorted->emplace_back(cur_op);
for(auto it = adj_list[cur_op].begin(); it != adj_list[cur_op].end(); it++){
indegree[it->first] -= it->second;
if (!indegree[it->first]) {
queue.push(it->first);
}
}
}
PADDLE_ENFORCE_EQ(cluster_sorted.size(), cluster.size(),
platform::errors::PreconditionNotMet(
"Cluster Sub-Graph shouldn't contain cycle."));
}
in_ops.emplace(n, 0); | ||
out_ops.emplace(n, std::vector<Node*>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这些赋值其实并没有什么必要。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in_ops.emplace(n, 0);
这个有必要吧?unordered_map
对于内置类型不会赋初始值0吧?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
std::unordered_map<Node*, size_t> in_ops; | ||
std::unordered_map<Node*, std::vector<Node*>> out_ops; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
建议使用indegree
和adj_list
命名,便于理解。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
好的,我改下
…o add_piano_graph_executor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
||
static const std::unordered_map<framework::proto::VarType::Type, | ||
note::ElementTypeProto>& | ||
GetVarType2NoteTypeMap() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
头文件中定义static 函数并不建议,而且你的map也是static的。如果被多个源文件包含,那么每个源文件会有一份独立的函数和变量。如果多个.cc文件引用这个头文件,会导致link变慢。不建议这么写。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done,已修改为extern
形式
return vartype2notetype; | ||
} | ||
|
||
static note::ElementTypeProto VarType2NoteType( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同上。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
note::ElementTypeProto VarType2NoteType(framework::proto::VarType::Type type) { | ||
const auto& vartype2notetype = GetVarType2NoteTypeMap(); | ||
PADDLE_ENFORCE_NE(vartype2notetype.find(type), vartype2notetype.end(), | ||
"Unsupported value data type (%s)", | ||
framework::DataTypeToString(type).c_str()); | ||
return vartype2notetype.at(type); | ||
} | ||
|
||
VarType::Type PianoGraphExecutor::GetVarDataType( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
感觉VarType2NoteType
和GetVarDataType
的定义可以拿出来放在vartype_utils.cc中,并将vartype2notetype.h
更改为vartype_utils.h
,让后将VarType2NoteType
和GetVarDataType
的声明放在vartype_utils.h
。GetVarDataType放在类中作为static函数,但是又感觉与PianoGraphExecutor无关。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
// Step2: create graph's input operand | ||
PianoScope scope; | ||
CreateInputOperand(&scope, &builder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1)将CreateInputOperand
声明为PianoScope CreateInputOperand(symbolization::NoteBuilder* builder)
,scope作为返回值。
2)TopologicSortCluster
改名为SortInternalCluster
并将签名换为GraphNodeVec SortInternalCluster()
。
以上两点建议是不是更好呢?
详见:https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/classes/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PianoScope
是DISABLE_COPY_AND_ASSIGN
的,所以不能直接返回,改为返回std::unique_ptr<PianoScope>
。另外SortInternalCluster
改为返回GraphNodeVec
并在调用处通过auto&&
避免拷贝。
symbolization::NoteBuilder builder(builder_name); | ||
|
||
// Step2: create graph's input operand | ||
auto&& scope = CreateInputOperand(&builder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这是在想通过右值引用延长变量的生命周期吗?其实个人感觉 auto scope = CreateInputOperand(&builder);
即可。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
// Step3: topo sort graph | ||
// rvalue references avoid useless copy | ||
auto&& cluster_sorted = SortInternalCluster(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个写成auto cluster_sorted = SortInternalCluster();
也是几乎没有开销的,调用的是vector的移动构造函数。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// store into PianoScope | ||
scope->SetOperand(var_name, op); | ||
} | ||
return std::move(scope); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里不需要写move,直接return scope;
即可。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
* 1. add interface for fft; 2. add data type predicate; 3. fix paddle.roll. * add fft c2c cufft kernel * implement argument checking & op calling parts for fft_c2c and fftn_c2c * add operator and opmaker definitions * only register float and double for cpu. * add common code for implementing FFT, add pocketfft as a dependency * add fft c2c cufft kernel function * fix bugs in python interface * add support for c2r, r2c operators, op makers, kernels and kernel functors. * test and fix bugs * 1. fft_c2c function: add support for onesided=False; 2. add complex<float>, complex<double> support for concat and flip. * 1. fft: fix python api bugs; 2. shape_op: add support for complex data types. * fft c2c cufft kernel done with complie and link * fix shape_op, add mkl placeholder * remove mkl * complete fft c2c in gpu * 1. implement mkl-based fft, FFTC2CFunctor and common function exec_fft; 2. change the design, add input and output typename as template parameter for all FFTFunctors, update pocketfft-based implementation. * complete fft c2c on gpu in ND * complete fft c2c on gpu in ND * complete fft c2c backward in ND * fix MKL-based implementation * Add frame op and CPU/GPU kernels. * Add frame op forward unittest. * Add frame op forward unittest. * Remove axis parameter in FrameFunctor. * Add frame op grad CPU/GPU kernels and unittest. * Add frame op grad CPU/GPU kernels and unittest. * Update doc string. * Update after review and remove librosa requirement in unittest. * Update grad kernel. * add fft_c2r op * Remove data allocation in TransCompute function. * add fft r2c onesided with cpu(pocketfft/mkl) and gpu * last fft c2r functor * fix C2R and R2C for cufft, becase the direction is not an option in these cases. * add fft r2c onesided with cpu(pocketfft/mkl) and gpu * fix bugs in python APIs * fix fft_c2r grad kernal * fix bugs in python APIs * add cuda fft c2r grad kernal functor * clean code * fix fft_c2r python API * fill fft r2c result with conjugate symmetry (#19) fill fft r2c result with conjugate symmetry * add placeholder for unittests (#24) * simple parameterize test function by auto generate test case from parm list (#25) * miscellaneous fixes for python APIs (#26) * add placeholder for unittests * resize fft inputs before computation is n or s is provided. * add complex kernels for pad and pad_grad * simplify argument checking. * add type promotion * add int to float or complex promotion * fix output data type for static mode * fix fft's input dtype dispatch, import fft to paddle * fix typos in axes checking (#27) * fix typos in axes checking * fix argument checking (#28) * fix argument checking * Add C2R Python layer normal and abnormal use cases (#29) * documents and single case * test c2r case * New C2R Python layer normal and exception use cases * complete rfft,rfft2,rfftn,ihfft,ihfft2,ihfftn unittest and doc string (#30) * Documentation of the common interfaces of c2r and c2c (#31) * Documentation of the common interfaces of c2r and c2c * clean c++ code (#32) * clean code * Add numpy-based implementation of spectral ops (#33) * add numpy reference implementation of spectral ops * Add fft_c2r numpy based implementation for unittest. (#34) * add fft_c2r numpy implementation * Add deframe op and stft/istft api. (#23) * Add frame api * Add deframe op and kernels. * Add stft and istft apis. * Add deframe api. Update stft and istft apis. * Fix bug in frame_from_librosa function when input dims >= 3 * Rename deframe to overlap_add. * Update istft. * Update after code review. * Add overlap_add op and stft/istft api unittest (#35) * Add overlap_add op unittest. * Register complex kernels of squeeze/unsquuze op. * Add stft/istft api unittest. * Add unittest for fft helper functions (#36) * add unittests for fft helper functions. add complex kernel for roll op. * complete static graph unittest for all public api (#37) * Unittest of op with FFT C2C, C2R and r2c added (#38) * documents and single case * test c2r case * New C2R Python layer normal and exception use cases * Documentation of the common interfaces of c2r and c2c * Unittest of op with FFT C2C, C2R and r2c added Co-authored-by: lijiaqi <lijiaqi0612@163.com> * add fft related options to CMakeLists.txt * fix typos and clean code (#39) * fix invisible character in mkl branch and fix error in error message * clean code: remove docstring from unittest for signal.py. * always convert numpy array to paddle.Tensor to avoid comparing numpy dtype with paddle dtype. (#40) * always convert numpy array to paddle.Tensor to avoid comparing numpy dtype with paddle dtype. * fix CI Errors: numpy dtype comparison, thrust when cuda is not available (#41) 1. always convert numpy array to paddle.Tensor to avoid comparing numpy dtype with paddle dtype. 2. promote floating point tensor to complex tensor ior fft_c2c and fft_c2r; 3. fix unittest to catch UnImplementedError and RuntimeError; 4. fix compile error by avoid using thrust when cuda is not available. 5. fix sample code, use paddle.fft instead of paddle.tensor.fft * remove inclusion of thrust, add __all__ list for fft (#42) * Add api doc and update unittest. (#43) * Add doc strings. * Update overlap_add op unittest * fix MKL-based FFT implementation (#44) * fix MKL-based FFT implementation, MKL CDFT's FORWARD DOMAIN is always REAL for R2C and C2R * remove code for debug (#45) * use dynload for cufft (#46) * use std::ptrdiff_t as datatype of stride (instead of int64_t) to avoid argument mismatch on some platforms. * add complex support for fill_zeros_like * use dynload for cufft * Update doc and unittest. (#47) * Add doc of frame op and overlap_add op. * Update unittest. * use dynload for cufft (#48) 1. use dynload for cufft 2. fix unittest; 3. temporarily disable Rocm. * fix conflicts and merge upstream (#49) fix conflicts and merge upstream * fix compile error: only link dyload_cuda when cuda is available (PaddlePaddle#50) * fix compile error: only link dyload_cuda when cuda is available * fix dynload for cufft on windows (PaddlePaddle#51) 1. fix dynload for cufft on windows; 2. fix unittests. * add NOMINMAX to compile on windows (PaddlePaddle#52) add NOMINMAX to compile on windows * explicitly specify capture mode for lambdas (PaddlePaddle#55) explicitly specify capture mode for lambdas * fix fft sample (PaddlePaddle#53) * fix fft sample * update scipy and numpy version for unittests of fft (PaddlePaddle#56) update scipy and numpy version for unittests of fft * Add static graph unittests of frame and overlap_add api. (PaddlePaddle#57) * Remove cache of cuFFT & Disable ONEMKL (PaddlePaddle#59) 1. replace numpy.fft with scipy.fft as numpy<1.20 not support ortho norm 2. remove cache of cufft plans; 3. enhance error checking. 4. default WITH_ONEMKL to OFF Co-authored-by: jeff41404 <jeff41404@gmail.com> Co-authored-by: root <root@bjyz-sys-gpu-kongming9.bjyz.baidu.com> Co-authored-by: KP <109694228@qq.com> Co-authored-by: lijiaqi <lijiaqi0612@163.com> Co-authored-by: Xiaoxu Chen <chenxx_id@163.com> Co-authored-by: lijiaqi0612 <33169170+lijiaqi0612@users.noreply.github.com>
PR types
New features
PR changes
Others
Describe
An executor accept sub-graph which is generated by PianoCompilePass, run each op's PianoOpKernel, finally return the graph's ModuleProto.
Parameter:
Describe:
The executor consisted by the following step: