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

【PIR OpTest Fix No.22】 fix test_elementwise_sub_op #62970

Closed

Conversation

Eddie-Wang1120
Copy link
Contributor

@Eddie-Wang1120 Eddie-Wang1120 commented Mar 24, 2024

PR Category

Others

PR Types

Others

Description

PIR Op单测修复
修复单测 test_elementwise_sub_op
修复后打开FLAGS_enable_pir_in_executor单测是否通过:是

报错函数:

template <typename T>
T* DenseTensor::data() {
  T* ret = static_cast<T*>(data());
  PADDLE_ENFORCE_EQ(
      dtype(),
      phi::CppTypeToDataType<T>::Type(),
      phi::errors::InvalidArgument(
          "The type of data we are trying to retrieve (%s) does not match the "
          "type of data (%s) currently contained in the container.",
          phi::CppTypeToDataType<T>::Type(),
          dtype()));
  return ret;
}

报错信息:
1711255588324
这里的错误为type not match错误,错误发生在处理输出类型为complex128时的,但比较奇怪的点有以下几点:

  • 打印前后计算图对比发现前后类型命名一致,选择的都是element_sub_grad kernel
  • elementwise_sub_op和elementwise_add_op等一系列elementwise_op在ops.yaml和backward.yaml已有定义好的前向反向op,且使用的是相同的正向反向infermeta,但add在complex未出现错误,sub出现错误。
  • 直接注释掉报错的PADDLE_ENFORCE_EQ后再次进行测试,发现单侧完全可以通过

疑问:

  • 此处代码应该是想对原始data进行转换,将原本的data强转为对应的c++格式,问题出现在该tensor的期望形式和要强转到的c++形式不一样,但因为这个函数名字比较大众,所以我实在找不到是在哪里调的这个函数,想请教一下paddle是否有打印c++完整错误栈的方式,或者说这个强制转换可能会发生在哪里,然后我再继续调一下这个函数。

Copy link

paddle-bot bot commented Mar 24, 2024

你的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.

@paddle-bot paddle-bot bot added the contributor External developers label Mar 24, 2024
@luotao1 luotao1 added the HappyOpenSource 快乐开源活动issue与PR label Mar 25, 2024
@xingmingyyj
Copy link
Contributor

这里怀疑是单测的问题,可以对比一下test/legacy_test/test_elementwise_sub_op.py和test/legacy_test/test_elementwise_add_op.py在complex类型上的测试逻辑是否一致@Eddie-Wang1120

@kangguangli
Copy link
Contributor

如果需要打印C++报错栈,可以尝试 export FLAGS_call_stack_level=2
另外准确的说这个不能算是强制转换,我们在DenseTensor这个结构体里存放里一块数据区域,通过data访问,这是个模板函数,参数是数据类型。在调用时我们会检测你传入的模板参数和为DenseTensor分配时赋予的Type是否一致,就是在这个时候报错。一般来说,这个调用都发生在kernel里面。
可以把执行器在执行的Program贴到这里看看。

@Eddie-Wang1120
Copy link
Contributor Author

这里怀疑是单测的问题,可以对比一下test/legacy_test/test_elementwise_sub_op.py和test/legacy_test/test_elementwise_add_op.py在complex类型上的测试逻辑是否一致@Eddie-Wang1120

好嘞好嘞我检查一下

@Eddie-Wang1120
Copy link
Contributor Author

如果需要打印C++报错栈,可以尝试 export FLAGS_call_stack_level=2 另外准确的说这个不能算是强制转换,我们在DenseTensor这个结构体里存放里一块数据区域,通过data访问,这是个模板函数,参数是数据类型。在调用时我们会检测你传入的模板参数和为DenseTensor分配时赋予的Type是否一致,就是在这个时候报错。一般来说,这个调用都发生在kernel里面。 可以把执行器在执行的Program贴到这里看看。

好的好的我试一下然后试着找一下错误原因

@Eddie-Wang1120
Copy link
Contributor Author

交换测试文件中虚数实数位置可以通过单侧,也即实数减虚数无法通过(纯比较output结果数值可以通过),虚数减实数可以通过。造成该问题的原因应该是elementsub算子推理出的out的type是错误的(应该?)(应为complex128实为float64),所以导致后面的mean操作中使用out作为输入时type不匹配,造成报错。但奇怪的是旧ir的计算图的out即为float64,且结果正确,并且新ir的elementwiseinfermeta方法中的promotetypes推理出的out类型就是complex128,但实际计算图打印的却为float64,属实非常奇怪。想请问一下目前这种情况可以算单侧通过吗,不能的话我再找一下原因。

@xingmingyyj
Copy link
Contributor

xingmingyyj commented Mar 30, 2024

交换测试文件中虚数实数位置可以通过单侧,也即实数减虚数无法通过(纯比较output结果数值可以通过),虚数减实数可以通过。造成该问题的原因应该是elementsub算子推理出的out的type是错误的(应该?)(应为complex128实为float64),所以导致后面的mean操作中使用out作为输入时type不匹配,造成报错。但奇怪的是旧ir的计算图的out即为float64,且结果正确,并且新ir的elementwiseinfermeta方法中的promotetypes推理出的out类型就是complex128,但实际计算图打印的却为float64,属实非常奇怪。想请问一下目前这种情况可以算单侧通过吗,不能的话我再找一下原因。

看了一下,现在的问题不是单测造成的。新ir的elementwiseinfermeta方法中的promotetypes推理出的out类型就是complex128,但实际计算图打印的却为float64的原因是新ir下的计算图是直接翻译旧IR下的计算图得到的,所以才会为float64。旧IR下能成功执行的原因猜测可能是他并没有依赖静态图中的信息,而是依赖了实际数据中的信息? 类似于#58379中的这个问题。这里当时遇到的问题是旧IR下静态图组网时候声明的数据类型为float32,但是数据传入的确实float64,造成新IR选出的Kernel和实际数据类型不匹配,但是旧IR下根据数据本身的类型去选Kernel,所以可以正确执行。这里感兴趣的话可以分析一下。如果是这个原因引起的话,这个算子的修复可能要设置特殊的翻译规则,需要和研发老师确认一下。

@Eddie-Wang1120
Copy link
Contributor Author

交换测试文件中虚数实数位置可以通过单侧,也即实数减虚数无法通过(纯比较output结果数值可以通过),虚数减实数可以通过。造成该问题的原因应该是elementsub算子推理出的out的type是错误的(应该?)(应为complex128实为float64),所以导致后面的mean操作中使用out作为输入时type不匹配,造成报错。但奇怪的是旧ir的计算图的out即为float64,且结果正确,并且新ir的elementwiseinfermeta方法中的promotetypes推理出的out类型就是complex128,但实际计算图打印的却为float64,属实非常奇怪。想请问一下目前这种情况可以算单侧通过吗,不能的话我再找一下原因。

看了一下,现在的问题不是单测造成的。新ir的elementwiseinfermeta方法中的promotetypes推理出的out类型就是complex128,但实际计算图打印的却为float64的原因是新ir下的计算图是直接翻译旧IR下的计算图得到的,所以才会为float64。旧IR下能成功执行的原因猜测可能是他并没有依赖静态图中的信息,而是依赖了实际数据中的信息? 类似于#58379中的这个问题。这里当时遇到的问题是旧IR下静态图组网时候声明的数据类型为float32,但是数据传入的确实float64,造成新IR选出的Kernel和实际数据类型不匹配,但是旧IR下根据数据本身的类型去选Kernel,所以可以正确执行。这里感兴趣的话可以分析一下。如果是这个原因引起的话,这个算子的修复可能要设置特殊的翻译规则,需要和研发老师确认一下。

了解了,非常感谢,我再仔细分析一下

@kangguangli
Copy link
Contributor

这里新旧IR共用同一个infermeta函数,新IR推导正确,旧IR应该也正确推导才对。
目前的修复方式不推荐,可以这样考虑:

  1. 组网阶段我们得到的静态图模型符合预期吗?数据类型是否正确?如果不正确,应该修改组网的代码
  2. 如果组网没有问题,是否单测设置的输入数据类型有误?
  3. 如果以上均无问题,那么流程应该进入翻译阶段,看看翻译得到的PIR 表示是否和旧IR一致,是否翻译过程出错?
  4. 然后是计算图的执行过程,以上均无问题,而执行器出错的概率是比较小的,但也有可能。具体来说,有这样几个地方可以确认:
  5. 从 op 到kernel的阶段是否有误,通过export FLAGS_print_ir=1可以看到lower前后program的变化,这里需要确认选到的kernel是否符合预期
  6. 接下来进入kernel的执行过程,kernel执行前会先执行infermeta重新推导,之后再拉起gpu kernel,这里可以尝试在 host端代码里加一点打印。

整体上目前的分析挺好的,后续推荐按我上面说的整理一下,把每个步骤的现状都贴在评论里,这样可以节省下大家的沟通时间,更快的定位问题。

@Eddie-Wang1120
Copy link
Contributor Author

我在test/legacy_test/op_test.py的第3758行后打印program计算图,我理解这里是静态图生成的计算图。
1711982357371
实数减虚数结果如下:
1711982117928
虚数减实数结果如下:
1711982173199
可见随着x、y位置的调换,生成的计算图结果出现了不同。按照我的理解,无论虚数减实数还是实数减虚数,结果(Out)都应是complex128类型,但现在实数减虚数的结果仍为float64,这也造成了后面执行mean时报错。
这是否能够说明组网阶段得到的静态图模型不符合预期呢?

Copy link

paddle-ci-bot bot commented Apr 6, 2024

Sorry to inform you that fba474f's CIs have passed for more than 7 days. To prevent PR conflicts, you need to re-run all CIs manually.

@kangguangli
Copy link
Contributor

我在test/legacy_test/op_test.py的第3758行后打印program计算图,我理解这里是静态图生成的计算图。 1711982357371 实数减虚数结果如下: 1711982117928 虚数减实数结果如下: 1711982173199 可见随着x、y位置的调换,生成的计算图结果出现了不同。按照我的理解,无论虚数减实数还是实数减虚数,结果(Out)都应是complex128类型,但现在实数减虚数的结果仍为float64,这也造成了后面执行mean时报错。 这是否能够说明组网阶段得到的静态图模型不符合预期呢?

抱歉回复得有点晚,这里不完全说明 模型不符合预期。 因为理论上对Tensor的二元运算是有类型提升规则的,是需要支持 x/y类型不同但是可以相减的。

这里我觉得可以深入排查的地方是subtract的infermeta,对应ElementwiseRawInferMeta,其中有下面这样的逻辑:

  paddle::experimental::DataTypeSet dtype_set{x.dtype()};
  dtype_set = dtype_set | paddle::experimental::DataTypeSet(y.dtype());
  DataType promote_result = PromoteTypes(dtype_set);
  if (promote_result == DataType::UNDEFINED) {
    promote_result = x.dtype();
  }
  out->set_dtype(promote_result);

在PromoteTypes中,x和y的dtype如果有任何一个是complex128,其返回结果就应该是 complex128,进而out也应该是 complex128。

所以后续可以先尝试排查下这里infermeta执行时的输入输出是否正确?是否out的dtype在这里是正确的,但被后续代码修改了?

@Eddie-Wang1120
Copy link
Contributor Author

我在test/legacy_test/op_test.py的第3758行后打印program计算图,我理解这里是静态图生成的计算图。 1711982357371 实数减虚数结果如下: 1711982117928 虚数减实数结果如下: 1711982173199 可见随着x、y位置的调换,生成的计算图结果出现了不同。按照我的理解,无论虚数减实数还是实数减虚数,结果(Out)都应是complex128类型,但现在实数减虚数的结果仍为float64,这也造成了后面执行mean时报错。 这是否能够说明组网阶段得到的静态图模型不符合预期呢?

抱歉回复得有点晚,这里不完全说明 模型不符合预期。 因为理论上对Tensor的二元运算是有类型提升规则的,是需要支持 x/y类型不同但是可以相减的。

这里我觉得可以深入排查的地方是subtract的infermeta,对应ElementwiseRawInferMeta,其中有下面这样的逻辑:

  paddle::experimental::DataTypeSet dtype_set{x.dtype()};
  dtype_set = dtype_set | paddle::experimental::DataTypeSet(y.dtype());
  DataType promote_result = PromoteTypes(dtype_set);
  if (promote_result == DataType::UNDEFINED) {
    promote_result = x.dtype();
  }
  out->set_dtype(promote_result);

在PromoteTypes中,x和y的dtype如果有任何一个是complex128,其返回结果就应该是 complex128,进而out也应该是 complex128。

所以后续可以先尝试排查下这里infermeta执行时的输入输出是否正确?是否out的dtype在这里是正确的,但被后续代码修改了?

好的我再仔细看一下

@luotao1 luotao1 closed this May 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contributor External developers HappyOpenSource 快乐开源活动issue与PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants