-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
【Complex op】add complex support for index_select and index_sample #56457
【Complex op】add complex support for index_select and index_sample #56457
Conversation
你的PR提交成功,感谢你对开源项目的贡献! |
int64_t, | ||
phi::dtype::complex<float>, | ||
phi::dtype::complex<double>) { | ||
kernel->InputAt(1).SetDataType(phi::DataType::INT64); |
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.
在这里改不太合适,可以试试在data_transform.cc 的NeedTransformDataType 中去掉对complex64和complex128的判断
@@ -554,6 +554,7 @@ void GradNodeBase::HandleComplexGradToRealGrad( | |||
for (size_t slot_id = 0; slot_id < out_grads->size(); slot_id++) { | |||
const std::vector<paddle::Tensor>& slot_out_grads = (*out_grads)[slot_id]; | |||
for (size_t rank_id = 0; rank_id < slot_out_grads.size(); rank_id++) { | |||
if (bwd_out_meta_[slot_id].size() == 0) continue; |
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.
- paddle/fluid/eager/api/generated/eager_generated/backwards/nodes.h 中生成了
IndexSelectGradNode
类(集成自egr::GradNodeBase
) - paddle/fluid/eager/api/generated/eager_generated/forwards/dygraph_functions.cc 中的
index_select_ad_func
函数里对IndexSelectGradNode
类进行了初始化其中 2 是根据grad_node = std::shared_ptr<IndexSelectGradNode>(new IndexSelectGradNode(1, 2));
ops.yaml
中 index_select 里 args 输入参数的数据类型确定的,即数据类型为 Tensor 的个数。 - paddle/fluid/eager/api/generated/eager_generated/backwards/nodes.cc 中的
IndexSelectGradNode::operator()
方法最后有:if(NeedComplexToRealConversion()) HandleComplexGradToRealGrad(&returns);
- paddle/fluid/eager/grad_node_info.cc 中的
GradNodeBase::HandleComplexGradToRealGrad
函数里的const GradSlotMeta& slot_meta = bwd_out_meta_[slot_id][rank_id];
会报错
原因在于 bwd_out_meta_ 初始化时的 size 为 2,但当 bwd_out_meta_[1] 所维持的 vector size 为 0,因此此处在执行 bwd_out_meta_[1][0] 时会造成 Segmentation faults.
所以在此处加了特判。
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.
那这里是不是不是根本问题?正常情况下,这里如果有out_grads, 那么对应的out_grad_meta应该也是记录好的才对,应该要看看为什么这里的out_grad_meta没有值
Sorry to inform you that 8a00648's CIs have passed for more than 7 days. To prevent PR conflicts, you need to re-run all CIs manually. |
Q: 为什么输入 x 的数据类型为 complex 的情况下,
|
|
反向传播问题index_select 和 index_sample 的输入均是两个 Tensor (x 和 index),但是它们对应的 grad 的输出只有一个 (x_grad). 在生成的 index_select_ad_func 方法 (dygraph_function.cc) 里, 会创建 IndexSelectGradNode (grad_node),其初始化时,传入的 bwd_out_slot_num 为 2。
bwd_out_slot_num 为 2 会使得 IndexSelectGradNode 中 bwd_out_meta_ 的大小为 2(它所包含的每一个元素也是一个 vector)。 // Set grad_node after API call
if(require_any_grad) {
egr::EagerUtils::PassStopGradient(false,out_autograd_meta);
// SetGradOutMeta & SetEdges
grad_node->SetGradOutMeta(x, 0);
// SetOutRank & SetHistory & SetGradInMeta
if (out_autograd_meta) {
egr::EagerUtils::SetOutRankWithSlot(out_autograd_meta, 0);
}
if (out_autograd_meta) {
egr::EagerUtils::SetHistory(out_autograd_meta, grad_node);
}
grad_node->SetGradInMeta(out, 0);
// Set TensorWrappers for Forward Outputs if needed
} 以上原因在于,index_select_grad 的配置中,输出只有一个 (x_grad)。导致在 eager_gen.py 生成 dygraph_function.cc 中,并不会对生成类似 而在 IndexSelectGradNode::operator() 方法中 (node.cc) 的最后,会有: if(NeedComplexToRealConversion()) HandleComplexGradToRealGrad(&returns); returns 的定义为: const auto& out_metas = OutputMeta();
paddle::small_vector<std::vector<paddle::Tensor>, egr::kSlotSmallVectorSize> returns(2);
for (int i = 0; i < 2; ++i) {
out_metas[i].size() == 0 ? returns[i].resize(1) : returns[i].resize(out_metas[i].size());
} out_metas 即为 bwd_out_meta_, 此时 out_metas[0].size() 为 1, out_metas[1].size 为 0. 最终导致 returns 中的两个元素的大小均为 1. 在 HandleComplexGradToRealGrad (grad_node_info.cc) 中,有 void GradNodeBase::HandleComplexGradToRealGrad(
paddle::small_vector<std::vector<paddle::Tensor>, kSlotSmallVectorSize>*
out_grads) {
for (size_t slot_id = 0; slot_id < out_grads->size(); slot_id++) {
const std::vector<paddle::Tensor>& slot_out_grads = (*out_grads)[slot_id];
for (size_t rank_id = 0; rank_id < slot_out_grads.size(); rank_id++) {
const GradSlotMeta& slot_meta = bwd_out_meta_[slot_id][rank_id]; 其中的 out_grads 即为 returns。 由于 returns 的大小为 2,且 returns[1].size() = 1. 但是 bwd_out_meta_[1].size() = 0. 因此当 slot_id=1, rank_id=0 时,bwd_out_meta_[1][0] 会 报错。 由于非 Complex 类型的数据并不会进入 HandleComplexGradToRealGrad 中,并不会对它们所造成影响。 |
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
前因后果很详细 👍👍👍 |
待该 PR merge 后,重新提个 PR 解决这个问题 |
麻烦 @heavyrain-lzy 帮忙 review 一下 :) |
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 for YAML file
@luotao1 所有的 Required CI 已经都过啦 |
…ddlePaddle#56457) * support index_select op * index_sample in cpu * support index_sample in gpu * change data_transform * fix api gen and use skip_transform in yaml
PR types
New features
PR changes
OPs
Description
add complex support for
index_select
andindex_sample
op