-
Notifications
You must be signed in to change notification settings - Fork 329
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
Lower krnl.call to llvm #1408
Lower krnl.call to llvm #1408
Conversation
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
The failure on Windows is caused by c compiler for runtime library. Dynamic arrays are used in the code, which is not accepted by the windows. The code looks like the following:
Related to this issue, array of dynamic array is not accepted by g++. It seems to me that I have to change the code to avoid that feature.
|
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
src/Runtime/OMResize.cpp
Outdated
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
//===--------- OMResize.cpp - OMResize C++ Implementation ---------===// |
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.
Fix line length
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.
Fixed.
src/Runtime/OMResize.cpp
Outdated
|
||
//===--------- OMResize.cpp - OMResize C++ Implementation ---------===// | ||
// | ||
// Copyright 2019-2021 The IBM Research Authors. |
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.
Copyright would be 2022 for new files.
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.
Fixed
**/ | ||
|
||
static void linear_coeffs(float ratio, float *coeffs_buffer, int mode) { | ||
coeffs_buffer[0] = 1 - ratio; |
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.
I'm just looking to this code without context and wondering how can we guarantee that coeffs_buffer
has at least 2 elements. Also coeffs_buffer
could be null. You could change the function signature to:
static void linear_coeffs(float ratio, float coeffs_buffer[2], int mode) {
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.
Also mode
is not used, can you remove it pls
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.
The implementation is translated from python code. Some types and parameters could be optimized as you suggested. I may keep some interface as its python counter part before the code is thoroughly tested.
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.
Those *_coeffs functions are passed by function pointers. The coeffs_buffer may have 2 or 3 elements. I changed code pointer for array declaration. I feel the benefit is to clearly show (to user) that at least how many elements this pointer should have. But the compiler will still treat that parameter as just pointer.
To have the same signature for function pointer, parameter mode
can not be deleted even it is not used in one function.
src/Runtime/OMResize.inc
Outdated
coeffs_buffer[1] = ratio; | ||
} | ||
|
||
static void nearest_coeffs(float ratio, float *coeffs_buffer, int mode) { |
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.
float *coeffs_buffer --> float coeffs_buffer[2]
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.
Fixed.
src/Runtime/OMResize.inc
Outdated
/* integer ratio is handled outside */ | ||
switch (mode) { | ||
case 0: // round_prefer_float | ||
coeffs_buffer[0] = ratio <= 0.5; |
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.
coeffs_buffer
is an array of float, but the values stored into it are actually of type _Bool
. Suffest to change its data type to _Bool
for C or bool
for C++.
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.
The original code takes the conversion of bool to float. I change the code to make it explicit: coeffs_buffer[0] = ration <= 0.5 ? 1 : 0;
, for all the assignments.
@@ -129,12 +129,27 @@ struct ONNXResizeOpLowering : public ConversionPattern { | |||
|
|||
// Call external function when the mode is not "nearest" | |||
// Create KrnlCallOp and replace the du chain | |||
// One of inputs, scales() and size(), has to be None. |
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.
One of the inputs, 'scales' or 'size', has to be 'None'.
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.
Yes, one of them has to be None. In general, the semantics of None is interpreted at the ONNX Op level. We could use tensor<0xT> for None and lower it to memref. So that we can keep None in Krnl and llvm after ONNX Op. We may have another PR for that functionality.
/*exclude */ 0); | ||
} | ||
|
||
void Resize_Size( |
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.
[nit]: I would name this resize_size
for consistency. Similar for resize_scales
.
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.
Resize comes from the ONNX Op name and Size or Scales comes from the attribute name. I can change function name for these two. But I am thinking of constructing the function name automatically. So can we just leave them?
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
//===------ KrnlCall.cpp - Lower KrnlCallOp -------------------===// |
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.
increase length
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.
Fixed
|
||
//===------ KrnlCall.cpp - Lower KrnlCallOp -------------------===// | ||
// | ||
// Copyright 2019-2022 The IBM Research Authors. |
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.
2019-2022 --> 2022
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.
Fixed
ConversionPatternRewriter &rewriter) const override { | ||
KrnlCallOpAdaptor krnlCallAdaptor(operands); | ||
auto loc = op->getLoc(); | ||
KrnlCallOp krnlCallOp = llvm::dyn_cast<KrnlCallOp>(op); |
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.
I think here we can use llvm::cast
given we are not checking whether krnlCallOp
is null
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.
true.
Value parameter, Value original, | ||
llvm::SmallVector<Type, 4> ¶meterTypeList, | ||
llvm::SmallVector<Value, 4> ¶meterList) { | ||
auto *context = op->getContext(); |
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.
LLVM code guidelines indicate that if the type of the RHS expression is not immediately clear from the context one should use the actual type rather than auto
.
tensorTy.dump(); | ||
auto memRefTy = | ||
MemRefType::get(tensorTy.getShape(), tensorTy.getElementType()); | ||
memRefTy.dump(); |
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.
naked trace leftover.
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.
deleted
Signed-off-by: chentong319 <chentong@us.ibm.com>
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, pending satisfying Ettore's comments
Jenkins Linux s390x Build #6346 [push] Lower krnl.call to llvm ... started at 11:04 |
Jenkins Linux amd64 Build #6330 [push] Lower krnl.call to llvm ... started at 10:04 |
Jenkins Linux ppc64le Build #5468 [push] Lower krnl.call to llvm ... started at 11:06 |
Jenkins Linux amd64 Build #6330 [push] Lower krnl.call to llvm ... failed after 16 min |
Jenkins Linux s390x Build #6346 [push] Lower krnl.call to llvm ... passed after 1 hr 18 min |
Jenkins Linux ppc64le Build #5468 [push] Lower krnl.call to llvm ... passed after 1 hr 27 min |
The new krnl.call supports that the returned value is a tensor, which is passed as a parameter to krnl.call. The krnl.call itself has no output. The read/write effect for parameters are set.
Parameters and attributes of krnl.call Op are turned into parameters for LLVM call op. The function type is determined by the types of parameters. In general, parameters with the tensor type or string type are passed by address, and those with scalar types are passed by value.
Since there is no lit test for krnl to llvm, I tested this PR with backend test. Since ResizeOp is quite complicated for deferent configuration, I manually translated the python implementation of ResizeOp in onnx package into c. 6 test cases are added to backend test.
This PR can be improved in several places. Since it is already quite large, I will leave the improvement for future PRs: