Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ace4713
Add addcmul operator for PaddlePaddle - Implement forward/backward ke…
Manfredss Jan 13, 2026
b7f40a1
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Jan 13, 2026
285af67
cpp sink for addcmul
Manfredss Jan 14, 2026
ca45edd
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Jan 14, 2026
8e8d4e4
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Jan 15, 2026
45b967f
fix for linux
Manfredss Jan 15, 2026
8773dc9
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Jan 21, 2026
a20a003
add converage for addcmul
Manfredss Jan 21, 2026
6919d31
del commented code and refine tests for addcmul
Manfredss Jan 21, 2026
b82d790
fix test
Manfredss Jan 22, 2026
5736202
fix
Manfredss Jan 23, 2026
6f3b32c
fix
Manfredss Jan 23, 2026
a582a5a
improve
Manfredss Jan 24, 2026
7e24908
coverage test
Manfredss Jan 25, 2026
a3ebc16
remove comment in ops.yaml and adjust testing code
Manfredss Jan 26, 2026
5ddba29
align with torch
Manfredss Jan 27, 2026
a1dcd98
Revert "align with torch"
Manfredss Jan 27, 2026
49bb3f2
signature align with torch and add unit test
Manfredss Jan 27, 2026
ed74700
use meaningful name and optimise mem alloc
Manfredss Jan 29, 2026
4a1f343
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Jan 30, 2026
fbaeb1b
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Feb 2, 2026
fdf3c92
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Feb 5, 2026
7ea3681
improve coverage
Manfredss Feb 6, 2026
4137182
skip test on XPU
Manfredss Feb 6, 2026
56d800b
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Feb 10, 2026
eb8b50a
skip XPU
Manfredss Feb 10, 2026
8144956
fix
Manfredss Feb 12, 2026
55f8f54
fix
Manfredss Feb 12, 2026
d530867
fix
Manfredss Mar 2, 2026
6c67637
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Mar 5, 2026
954ceec
fix
Manfredss Mar 6, 2026
b331c0d
fix
Manfredss Mar 7, 2026
5ce27ed
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Apr 3, 2026
d82eb97
align api
Manfredss Apr 4, 2026
a733490
fix tests
Manfredss Apr 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,84 @@ bool AccuracyOpInferSymbolicShape(
return true;
}

bool AddcmulOpInferSymbolicShape(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

这个逻辑在单测里测试到了没,这个需要开CINN才能测到:check_cinn=True

pir::Operation *op, pir::InferSymbolicShapeContext *infer_context) {
const auto &input_shape_or_data =
infer_context->GetShapeOrDataForValue(op->operand_source(0));
const auto &tensor1_shape_or_data =
infer_context->GetShapeOrDataForValue(op->operand_source(1));
const auto &tensor2_shape_or_data =
infer_context->GetShapeOrDataForValue(op->operand_source(2));
std::vector<symbol::DimExpr> input_shape = input_shape_or_data.shape();
std::vector<symbol::DimExpr> tensor1_shape = tensor1_shape_or_data.shape();
std::vector<symbol::DimExpr> tensor2_shape = tensor2_shape_or_data.shape();

// Step 1: Broadcast tensor1 and tensor2 (matches InferMeta order)
int tensor1_ndims = static_cast<int>(tensor1_shape.size());
int tensor2_ndims = static_cast<int>(tensor2_shape.size());
int diff_t1_t2 = tensor1_ndims - tensor2_ndims;
if (diff_t1_t2 > 0) {
for (int i = 0; i < diff_t1_t2; ++i) {
tensor2_shape.emplace(tensor2_shape.begin(), 1);
}
} else {
for (int i = 0; i < -diff_t1_t2; ++i) {
tensor1_shape.emplace(tensor1_shape.begin(), 1);
}
}

symbol::DimExprBuilder builder;
std::vector<symbol::DimExpr> mul_shape;
for (size_t i = 0; i < tensor1_shape.size(); ++i) {
if (tensor1_shape[i] == tensor2_shape[i]) {
mul_shape.emplace_back(tensor1_shape[i]);
} else if (tensor1_shape[i] == 1) {
mul_shape.emplace_back(tensor2_shape[i]);
} else if (tensor2_shape[i] == 1) {
mul_shape.emplace_back(tensor1_shape[i]);
} else {
mul_shape.emplace_back(
builder.Broadcast(tensor1_shape[i], tensor2_shape[i]));
infer_context->AddBroadcastableCstr(tensor1_shape[i], tensor2_shape[i]);
}
}

// Step 2: Broadcast input and mul_shape (matches InferMeta order)
int input_ndims = static_cast<int>(input_shape.size());
int mul_ndims = static_cast<int>(mul_shape.size());
int diff_input_mul = input_ndims - mul_ndims;
if (diff_input_mul > 0) {
for (int i = 0; i < diff_input_mul; ++i) {
mul_shape.emplace(mul_shape.begin(), 1);
}
} else {
for (int i = 0; i < -diff_input_mul; ++i) {
input_shape.emplace(input_shape.begin(), 1);
}
}

std::vector<symbol::DimExpr> output_shape;
for (size_t i = 0; i < input_shape.size(); ++i) {
if (input_shape[i] == mul_shape[i]) {
output_shape.emplace_back(input_shape[i]);
} else if (input_shape[i] == 1) {
output_shape.emplace_back(mul_shape[i]);
} else if (mul_shape[i] == 1) {
output_shape.emplace_back(input_shape[i]);
} else {
output_shape.emplace_back(
builder.Broadcast(input_shape[i], mul_shape[i]));
infer_context->AddBroadcastableCstr(input_shape[i], mul_shape[i]);
}
}

infer_context->SetShapeOrDataForValue(
op->result(0),
symbol::ShapeOrDataDimExprs{
symbol::TensorShapeOrDataDimExprs(output_shape)});
return true;
}

bool AddNOpInferSymbolicShape(pir::Operation *op,
pir::InferSymbolicShapeContext *infer_context) {
const auto &input_list_shape_or_data =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
namespace paddle::dialect {

OP_DECLARE_INFER_SYMBOLIC_SHAPE(Accuracy)
OP_DECLARE_INFER_SYMBOLIC_SHAPE(Addcmul)
OP_DECLARE_INFER_SYMBOLIC_SHAPE(Addmm)
OP_DECLARE_INFER_SYMBOLIC_SHAPE(Addmm_)
OP_DECLARE_INFER_SYMBOLIC_SHAPE(AddN)
Expand Down
48 changes: 48 additions & 0 deletions paddle/phi/infermeta/ternary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ limitations under the License. */
#include "paddle/phi/kernels/funcs/common_shape.h"
#include "paddle/phi/kernels/impl/box_coder.h"

#include "paddle/phi/core/infermeta_utils.h"
#include "paddle/phi/core/meta_tensor.h"

namespace phi {
namespace detail {
// Used in MatrixRankAtolRtolInferMeta
Expand Down Expand Up @@ -139,6 +142,51 @@ void AddmmInferMeta(const MetaTensor& input,
out->set_dtype(input.dtype());
}

static DDim BroadcastTwoDims(const DDim& x_dims, const DDim& y_dims) {
int max_rank = std::max(x_dims.size(), y_dims.size());
std::vector<int64_t> out_dims_vector(max_rank);

int x_idx = x_dims.size() - 1;
int y_idx = y_dims.size() - 1;

for (int i = max_rank - 1; i >= 0; --i) {
int64_t x_val = x_idx >= 0 ? x_dims[x_idx--] : 1;
int64_t y_val = y_idx >= 0 ? y_dims[y_idx--] : 1;

// Check broadcast validity (dimensions must be equal, or one of them is 1)
if (x_val != y_val && x_val != 1 && y_val != 1) {
PADDLE_THROW(common::errors::InvalidArgument(
"Broadcast dimension mismatch. Operands could not be broadcast "
"together with shapes %s and %s",
x_dims,
y_dims));
}
out_dims_vector[i] = std::max(x_val, y_val);
}
return common::make_ddim(out_dims_vector);
}

void AddcmulInferMeta(const MetaTensor& input,
const MetaTensor& tensor1,
const MetaTensor& tensor2,
MetaTensor* out) {
auto input_dims = input.dims();
auto t1_dims = tensor1.dims();
auto t2_dims = tensor2.dims();

// 1. First broadcast tensor1 and tensor2 (corresponding to value * tensor1 *
// tensor2)
DDim mul_dims = BroadcastTwoDims(t1_dims, t2_dims);

// 2. Then broadcast the result with input (corresponding to input + ...)
DDim out_dims = BroadcastTwoDims(input_dims, mul_dims);

// 3. Set output information
out->set_dims(out_dims);
out->share_lod(input);
out->set_dtype(input.dtype());
}

void BaddbmmInferMeta(const MetaTensor& input,
const MetaTensor& x,
const MetaTensor& y,
Expand Down
5 changes: 5 additions & 0 deletions paddle/phi/infermeta/ternary.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ PADDLE_API void AccuracyInferMeta(const MetaTensor& out,
MetaTensor* total,
MetaConfig config = MetaConfig());

PADDLE_API void AddcmulInferMeta(const MetaTensor& input,
const MetaTensor& tensor1,
const MetaTensor& tensor2,
MetaTensor* out);

PADDLE_API void AddmmInferMeta(const MetaTensor& input,
const MetaTensor& x,
const MetaTensor& y,
Expand Down
33 changes: 33 additions & 0 deletions paddle/phi/kernels/addcmul_grad_kernel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "paddle/phi/common/scalar.h"
#include "paddle/phi/core/dense_tensor.h"

namespace phi {

template <typename T, typename Context>
void AddcmulGradKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& tensor1,
const DenseTensor& tensor2,
const DenseTensor& out_grad,
const Scalar& value,
DenseTensor* input_grad,
DenseTensor* tensor1_grad,
DenseTensor* tensor2_grad);

} // namespace phi
30 changes: 30 additions & 0 deletions paddle/phi/kernels/addcmul_kernel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "paddle/phi/common/scalar.h"
#include "paddle/phi/core/dense_tensor.h"

namespace phi {

template <typename T, typename Context>
void AddcmulKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& tensor1,
const DenseTensor& tensor2,
const Scalar& value,
DenseTensor* out);

} // namespace phi
22 changes: 22 additions & 0 deletions paddle/phi/kernels/cpu/addcmul_grad_kernel.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/phi/kernels/addcmul_grad_kernel.h"

#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/addcmul_grad_kernel_impl.h"

PD_REGISTER_KERNEL(
addcmul_grad, CPU, ALL_LAYOUT, phi::AddcmulGradKernel, float, double) {}
23 changes: 23 additions & 0 deletions paddle/phi/kernels/cpu/addcmul_kernel.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/phi/kernels/addcmul_kernel.h"

#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/addcmul_kernel_impl.h"

PD_REGISTER_KERNEL(
addcmul, CPU, ALL_LAYOUT, phi::AddcmulKernel, float, double, int, int64_t) {
}
14 changes: 13 additions & 1 deletion paddle/phi/kernels/funcs/common_shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,19 @@ static void GetBroadcastDims(const DDim &in_dims,
if (in_dims[i] == out_dims[i]) {
(*bcast_dims)[i] = 1;
} else {
(*bcast_dims)[i] = std::max(in_dims[i], out_dims[i]);
// Calculate broadcast factor: out_dims[i] / in_dims[i]
// in_dims[i] should be 1 for valid broadcasting
PADDLE_ENFORCE_EQ(
in_dims[i],
1,
common::errors::InvalidArgument(
"Tensor dimension mismatch for broadcasting. "
"Input dimension %d is %d, output dimension is %d. "
"For broadcasting, input dimension must be 1 or equal to output.",
i,
in_dims[i],
out_dims[i]));
(*bcast_dims)[i] = out_dims[i];
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions paddle/phi/kernels/gpu/addcmul_grad_kernel.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/phi/kernels/addcmul_grad_kernel.h"

#include "paddle/phi/backends/gpu/gpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/addcmul_grad_kernel_impl.h"

PD_REGISTER_KERNEL(addcmul_grad,
GPU,
ALL_LAYOUT,
phi::AddcmulGradKernel,
float,
double,
phi::dtype::float16,
phi::dtype::bfloat16) {}
30 changes: 30 additions & 0 deletions paddle/phi/kernels/gpu/addcmul_kernel.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/phi/kernels/addcmul_kernel.h"

#include "paddle/phi/backends/gpu/gpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/addcmul_kernel_impl.h"

PD_REGISTER_KERNEL(addcmul,
GPU,
ALL_LAYOUT,
phi::AddcmulKernel,
float,
double,
phi::dtype::float16,
phi::dtype::bfloat16,
int,
int64_t) {}
Loading
Loading