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

【PTen】C++ API Code-Generation #37668

Merged
merged 19 commits into from
Dec 3, 2021
Merged

Conversation

zyfncg
Copy link
Contributor

@zyfncg zyfncg commented Nov 29, 2021

PR types

Breaking changes

PR changes

APIs

Describe

目标:通过文件配置完成PTen中C++ API的代码自动生成,减少C++ API的开发成本
方案概览:使用yaml文件进行C++ API代码的生成配置(主要包括API的接口命名、输入输出参数、使用的InferMeta函数、调用的计算kernel以及kernel的选择配置等),在程序构建时会读取yaml配置文件进行解析并生成对应的C++ API代码(包括声明API的头文件和API实现逻辑的源文件)。

API配置文件格式:
以matmul和 full_like为例:

- api : matmul 
  args : (const Tensor& x, const Tensor& y, bool transpose_x = false, bool transpose_y = false)
  output : Tensor
  infer_meta : 
    func : MatmulInferMeta
  kernel : 
    func : matmul_v2

- api : full_like
  args : (const Tensor& x, const Scalar& value, DataType dtype = DataType::UNDEFINED, Backend place = Backend::UNDEFINED, DataLayout layout = DataLayout::UNDEFINED)
  output: Tensor
  infer_meta : 
    func : FullLikeInferMeta
    param : [x, dtype, layout]
  kernel : 
    func : fill_any_like
    param : [x, value]
    data_type : dtype > x
    backend : place > x
    layout : layout > x

其中各项配置参数的含义:
api : 生成API的函数名
args : API的输入参数,与普通C++函数参数格式相同,非Tensor类型输入参数可设置默认值
output : 返回参数类型,支持Tensor与vector<Tensor>
infer_meta : 生成返回Tensor的Meta信息
    func : 调用的InferMeta函数
    param : InferMeta函数的输入参数,如果与API的输入参数相同,可以省略不写(如matmul示例)
kernel :  kernel配置
    func : 调用的kernel函数(使用kernel注册名)
    param : kernel的输入参数,如果与API的输入参数相同,可以省略不写(如matmul示例)
    data_type : 调用kernel的data_type类型(对应kernel函数的模板参数T)
    backend : 执行kernel的计算设备
    layout : kernel的layout配置

生成API代码示例(matmul):

PD_DLL_DECL Tensor matmul(const Tensor& x, const Tensor& y, bool transpose_x, bool transpose_y) {

  Backend kernel_backend = Backend::UNDEFINED;
  DataLayout kernel_layout = DataLayout::UNDEFINED;
  DataType kernel_data_type = DataType::UNDEFINED;

  if (kernel_backend == Backend::UNDEFINED 
        || kernel_layout == DataLayout::UNDEFINED
        || kernel_data_type == DataType::UNDEFINED ) {
    auto kernel_key_set = ParseKernelKeyByInputArgs(x, y);
    auto kernel_key = kernel_key_set.GetHigestPriorityKernelKey();
    if (kernel_backend == Backend::UNDEFINED) {
      kernel_backend = kernel_key.backend();
    }
    if (kernel_layout == DataLayout::UNDEFINED) {
      kernel_layout = kernel_key.layout();
    }
    if (kernel_data_type == DataType::UNDEFINED) {
      kernel_data_type = kernel_key.dtype();
    }
  }
  auto kernel = pten::KernelFactory::Instance().SelectKernelOrThrowError(
      "matmul_v2", {kernel_backend, kernel_layout, kernel_data_type});

  auto* dev_ctx = GetDeviceContextByBackend(kernel_backend);
  auto kernel_context = pten::KernelContext(dev_ctx);

  auto dense_x = std::dynamic_pointer_cast<pten::DenseTensor>(x.impl());
  kernel_context.EmplaceBackInput(dense_x);
  auto dense_y = std::dynamic_pointer_cast<pten::DenseTensor>(y.impl());
  kernel_context.EmplaceBackInput(dense_y);

  kernel_context.EmplaceBackAttr(transpose_x);
  kernel_context.EmplaceBackAttr(transpose_y);

  auto out_meta = pten::MatmulInferMeta(dense_x->meta(), dense_y->meta(), transpose_x, transpose_y);

  const auto allocator =
      std::make_shared<paddle::experimental::DefaultAllocator>(
          pten::TransToFluidPlace(kernel_backend));
  auto dense_out = std::make_shared<pten::DenseTensor>(allocator, out_meta);
  kernel_context.EmplaceBackOutput(dense_out);

  Tensor out;
  out.set_impl(dense_out);

  kernel(&kernel_context);
  return out;
}

从整体效果看,使用API自动生成将原来需要手动编写的几十行API代码简化为10行左右的配置文件,可以有效降低C++ API的开发成本

@paddle-bot-old
Copy link

Thanks for your contribution!
Please wait for the result of CI firstly. See Paddle CI Manual for details.



def license():
return """
Copy link
Contributor

@MingMingShangTian MingMingShangTian Nov 30, 2021

Choose a reason for hiding this comment

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

编译期间生成的文件,license 不用添加

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

YuanRisheng
YuanRisheng previously approved these changes Nov 30, 2021
Copy link
Contributor

@chenwhql chenwhql left a comment

Choose a reason for hiding this comment

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

LGTM,先有初版,细节设计后续可以按需迭代完善

output : Tensor
invoke : full_like(x, 0, dtype, place, layout)

# - api : full_like
Copy link
Contributor

Choose a reason for hiding this comment

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

如果是非必要的注释,建议后续PR移除

Copy link
Contributor Author

Choose a reason for hiding this comment

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

这里想的是放一个不同的API定义格式用来对比和进行讨论,后续PR中会删除

@zyfncg zyfncg merged commit c58c4ed into PaddlePaddle:develop Dec 3, 2021
Zjq9409 pushed a commit to Zjq9409/Paddle that referenced this pull request Dec 10, 2021
* add code-gen file

* add api-gen in cmake

* adjust the code format

* temp save the code

* add genen-api module into pten

* merge the develop code

* fix merge conflict

* fix code conflict with develop

* support reduce_mean/sum

* fix the CI requirement

* fix requirement problem of CI

* remove original api code

* fix bug caused by removing original api
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants