Skip to content
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

Merged
merged 35 commits into from
Jun 10, 2022
Merged

Lower krnl.call to llvm #1408

merged 35 commits into from
Jun 10, 2022

Conversation

chentong319
Copy link
Collaborator

@chentong319 chentong319 commented May 5, 2022

  1. Modified the krnl.call definition and builder.
    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.
  2. Lower krnl.call to llvm
    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.
  3. Test with 6 new test cases that use the krnl.call.
    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.
  4. Some document for krnl.region

This PR can be improved in several places. Since it is already quite large, I will leave the improvement for future PRs:

  1. Handle optional input tensor with NoneType in a more generic way. Hopefully, null pointer can be used and leave the runtime library to handle it, reducing the number of runtime functions needed.
  2. Propagate attributes with default value. Such attribute may not appear in the Op and is lost when the op is translated to krnl.call. Also all the attributes are blindly copied. If an attribute, not from ONNX Op specification, is added, krnl.call will have an extra parameter for that attribute.
  3. The Resize runtime is very inefficient.
  4. Only some configuration of ResizeOp is supported by runtime library currently.

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>
Signed-off-by: chentong319 <chentong@us.ibm.com>
Signed-off-by: chentong319 <chentong@us.ibm.com>
@chentong319
Copy link
Collaborator Author

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:

void foo(int n) {
float a[n];
}

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.

void f(int n, float a[][n]){
    a[k][j] = 0;
}
void g(int n, int m) {
    float b[m][n];
    f(n, b);
}

chentong319 and others added 11 commits May 6, 2022 11:38
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>
* SPDX-License-Identifier: Apache-2.0
*/

//===--------- OMResize.cpp - OMResize C++ Implementation ---------===//
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix line length

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


//===--------- OMResize.cpp - OMResize C++ Implementation ---------===//
//
// Copyright 2019-2021 The IBM Research Authors.
Copy link
Collaborator

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.

Copy link
Collaborator Author

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;
Copy link
Collaborator

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) {

Copy link
Collaborator

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

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

coeffs_buffer[1] = ratio;
}

static void nearest_coeffs(float ratio, float *coeffs_buffer, int mode) {
Copy link
Collaborator

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]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

/* integer ratio is handled outside */
switch (mode) {
case 0: // round_prefer_float
coeffs_buffer[0] = ratio <= 0.5;
Copy link
Collaborator

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++.

Copy link
Collaborator Author

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.
Copy link
Collaborator

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'.

Copy link
Collaborator Author

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(
Copy link
Collaborator

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.

Copy link
Collaborator Author

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 -------------------===//
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

increase length

Copy link
Collaborator Author

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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2019-2022 --> 2022

Copy link
Collaborator Author

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);
Copy link
Collaborator

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true.

src/Conversion/KrnlToLLVM/KrnlCall.cpp Outdated Show resolved Hide resolved
Value parameter, Value original,
llvm::SmallVector<Type, 4> &parameterTypeList,
llvm::SmallVector<Value, 4> &parameterList) {
auto *context = op->getContext();
Copy link
Collaborator

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.

src/Conversion/KrnlToLLVM/KrnlCall.cpp Outdated Show resolved Hide resolved
src/Conversion/KrnlToLLVM/KrnlCall.cpp Outdated Show resolved Hide resolved
tensorTy.dump();
auto memRefTy =
MemRefType::get(tensorTy.getShape(), tensorTy.getElementType());
memRefTy.dump();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naked trace leftover.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

Copy link
Collaborator

@AlexandreEichenberger AlexandreEichenberger left a 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

@AlexandreEichenberger AlexandreEichenberger merged commit 5a321d2 into onnx:main Jun 10, 2022
@jenkins-droid
Copy link
Collaborator

Jenkins Linux s390x Build #6346 [push] Lower krnl.call to llvm ... started at 11:04

@jenkins-droid
Copy link
Collaborator

Jenkins Linux amd64 Build #6330 [push] Lower krnl.call to llvm ... started at 10:04

@jenkins-droid
Copy link
Collaborator

Jenkins Linux ppc64le Build #5468 [push] Lower krnl.call to llvm ... started at 11:06

@jenkins-droid
Copy link
Collaborator

Jenkins Linux amd64 Build #6330 [push] Lower krnl.call to llvm ... failed after 16 min

@jenkins-droid
Copy link
Collaborator

Jenkins Linux s390x Build #6346 [push] Lower krnl.call to llvm ... passed after 1 hr 18 min

@jenkins-droid
Copy link
Collaborator

Jenkins Linux ppc64le Build #5468 [push] Lower krnl.call to llvm ... passed after 1 hr 27 min

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants