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

Add output defs for topk kernel #51233

Merged

Conversation

From00
Copy link
Contributor

@From00 From00 commented Mar 6, 2023

PR types

Others

PR changes

Others

Describe

Pcard-67003

本PR作为飞桨快乐开源活动issue #51292 的示范例子,为top_k算子的输出参数indices注册数据类型DataType。

以下为修复top_k算子注册信息的过程,参与任务的开发者可参照实现对其它算子注册信息的修复:

1. 阅读kernel实现
paddle/phi/kernels目录下找到top_k算子的kernel代码,可以发现TopKKernel函数有outindices两个输出Tensor,分别表示查找到的top-k结果以及对应的索引信息;其中out的数据类型与kernel类型一致,但indices的数据类型int64_t与kernel类型不一致,需要进行注册。

template <typename T, typename Context>
void TopkKernel(const Context& dev_ctx,
                const DenseTensor& x,
                const Scalar& k_scalar,
                int axis,
                bool largest,
                bool sorted,
                DenseTensor* out,
                DenseTensor* indices) {
    ...
    T* output_data = dev_ctx.template Alloc<T>(out);
    int64_t* indices_data = dev_ctx.template Alloc<int64_t>(indices);
    ...                    
  }

我们可以通过kernel中分配内存(AllocHostAlloc)的操作,来判断一个输出Tensor的DataType信息。若在分配内存时传入kernel实例化的模板参数T,则表示该输出Tensor数据类型与kernel一致,这种情况不需要专门做注册(未注册的参数数据类型默认与kernel相同);若分配内存时传入与T不同的模板参数,则表示该输出Tensor数据类型与kernel不一致,需要做注册。
除了通过阅读代码进行判断,也可以查阅算子对应的API文档,文档中一般都会说明输出参数的数据类型。

2. 添加注册信息
判断出top_kindices参数需要注册数据类型后,找到top_k的kernel注册代码,在注册宏的花括号{}中设置输出参数的数据类型:

kernel->OutputAt(1).SetDataType(phi::DataType::INT64);

kernel->OutputAt()中传入注册DataType的输出参数编号,编号从0开始,按kernel函数声明中的位置依次递增。如top_k kernel的第0个输出为out,第1个输出为indices

注意:本PR代码中DataType使用了paddle::experimental::命名空间,这是算子库项目开发初期使用的命名空间。paddle::experimental::DataTypephi::DataType是等价的,后续按规范要求,需要统一成phi::DataType。存量代码的改造工作正在进行中,增量代码需直接使用phi::DataType

在添加注册信息时,若该算子分开注册了多种类型的kernel,对于每种kernel都需要添加上输出参数的数据类型。如top_k算子在cpu/top_k_kernel.ccgpu/top_k_kernel.cuxpu/top_k_kernel.cc中分别注册了cpu、gpu和xpu三种kernel,需要在这三处注册代码中都分别添加数据类型注册。一般来说,一个算子至少会分开注册cpu、gpu和xpu三种不同的后端设备类型,某些算子还会分开注册不同的DataType和Layout类型。

由于静态图中通过黑名单机制对一些未规范注册DataType的算子屏蔽了全静态选kernel功能,在完成算子的DataType注册后,请顺手将其从黑名单中移除。

有些算子的输出数据类型是无法静态确定的,需要根据一些输入信息进行推导,此时可对该参数注册UNDEFINED类型。注册UNDEFINED的参数需要通过InferMeta进行推导,因此,若对某个参数注册了UNDEFINED,你需要确保该算子的InferMeta已被正确地实现和注册。具体地,你需要:
(1)在paddle/phi/infermeta/目录下找到该算子的InferMeta实现,检查该算子的InferMeta中是否正确实现了UNDEFINED参数的DataType推导逻辑,若未实现或实现有误,则需要你对相关逻辑进行修复。关于InferMeta的实现,可参考《开发C++算子》文档中实现InferMeta函数一节。
(2)在paddle/fluid/operators/目录下找到该算子的注册信息,确保该算子的InferShape已迁移成phi下的InferMeta。若一个算子的InferShape已迁移,则该算子不会实现InferShape函数,且在算子注册时会注册xxxInferShapeFunction的信息;若未迁移,则需要你对该算子的InferShape进行迁移。关于InferShape的迁移,可参考PR #39517

3. 代码测试
本次任务不需要专门新写单测进行验证,在完成问题修复后,找到修复算子对应的单测,运行该单测进行验证即可。算子的单测通常被命名为test_xxx_op的形式,如test_top_k_op。如果你在本地无法找到算子对应的单测,可以在编译通过后提交PR跑CI测试,CI系统会对对应算子的单测进行测试,并反馈给你测试失败的单测列表。

@paddle-bot
Copy link

paddle-bot bot commented Mar 6, 2023

你的PR提交成功,感谢你对开源项目的贡献!
请关注后续CI自动化测试结果,详情请参考Paddle-CI手册
Your PR has been submitted. Thanks for your contribution!
Please wait for the result of CI firstly. See Paddle CI Manual for details.

@From00 From00 merged commit b5232bf into PaddlePaddle:develop Mar 7, 2023
@From00 From00 deleted the add-output-defs-for-top-k-kernel branch April 5, 2023 09:05
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.

2 participants