Files
2026-07-13 12:40:42 +08:00

269 lines
8.9 KiB
C++

// Copyright (c) 2025 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 <optional>
#include "paddle/common/ddim.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/utils/small_vector.h"
namespace phi {
struct DenseTensorIteratorConfig;
struct DenseTensorIterator;
struct Tensor32BitSplitter;
enum struct FastSetupType : uint8_t { NONE, CONTIGUOUS };
/**
* DenseOperandInfo: Used to store tensor-related information.
* Contains metadata and details about tensors participating in operations.
*/
struct DenseOperandInfo {
DenseOperandInfo() = default;
inline explicit DenseOperandInfo(DenseTensor*&& t) {
if (t->initialized()) {
target_dtype = t->dtype();
current_dtype = target_dtype;
}
tensor(std::move(t));
}
inline DenseOperandInfo(const DenseOperandInfo&) = default;
inline DenseOperandInfo& operator=(const DenseOperandInfo&) = default;
inline DenseOperandInfo(DenseOperandInfo&&) noexcept = default;
inline DenseOperandInfo& operator=(DenseOperandInfo&&) noexcept = default;
inline ~DenseOperandInfo() = default;
void* data = nullptr;
std::vector<int64_t> stride_bytes;
DataType target_dtype = DataType::UNDEFINED;
DataType current_dtype = DataType::UNDEFINED;
bool is_output = false;
bool will_resize = false;
bool is_read_write = false;
bool is_const = false;
bool is_type_defined() const { return target_dtype != DataType::UNDEFINED; }
DenseTensor& tensor() const { return *tensor_base_; }
void tensor(DenseTensor*&& tensor);
private:
DenseTensor* tensor_base_;
};
/**
* DenseTensorIteratorBase: Base class for DenseTensorIterator.
* Defines and supports the key functions used by DenseTensorIterator.
*/
struct DenseTensorIteratorBase {
void build(DenseTensorIteratorConfig&);
int ndim() const { return static_cast<int>(shape_.size()); }
const std::vector<int64_t>& shape() const { return shape_; }
int64_t numel() const;
int ntensors() const { return static_cast<int>(operands_.size()); }
bool is_contiguous() const;
int64_t num_output_elements() const;
int noutputs() const { return num_outputs_; }
int num_reduce_dims() const;
const std::vector<int64_t>& strides(int64_t arg) const {
return operands_[arg].stride_bytes;
}
DataType dtype(int64_t arg = 0) const { return operands_[arg].current_dtype; }
std::vector<int64_t> view_offsets() const { return view_offsets_; }
void* data_ptr(int64_t arg) const;
bool should_accumulate() const { return accumulate_; }
bool is_final_output() const { return final_output_; }
int get_dim_to_split() const;
bool is_dim_reduced(int dim) const;
std::unique_ptr<DenseTensorIterator> split(int dim);
protected:
void populate_operands(DenseTensorIteratorConfig&);
void compute_shape(const DenseTensorIteratorConfig&);
void compute_strides(const DenseTensorIteratorConfig&);
void reorder_dimensions();
void permute_dimensions(std::vector<int64_t> perm);
void allocate_or_resize_outputs();
bool fast_set_up(const DenseTensorIteratorConfig&);
FastSetupType compute_fast_setup_type(const DenseTensorIteratorConfig&);
void coalesce_dimensions();
void narrow(int dim, int64_t start, int64_t size);
protected:
std::vector<int64_t> shape_;
std::vector<int64_t> perm_;
std::vector<int64_t> view_offsets_;
bool has_coalesced_dimensions_ = false;
size_t num_outputs_ = 0;
bool all_ops_same_shape_ = false;
bool all_ops_are_scalars_ = false;
public:
std::vector<DenseOperandInfo> operands_;
std::vector<int64_t> compatible_stride(int64_t element_size) const;
std::vector<int64_t> invert_perm(std::vector<int64_t> input) const;
bool can_use_32bit_indexing() const;
Tensor32BitSplitter with_32bit_indexing() const;
virtual void set_output_raw_strided(int64_t output_idx,
std::vector<int64_t> sizes,
std::vector<int64_t> strides);
bool is_reduction_ = false;
bool is_alloc_out_ = false;
bool accumulate_ = false;
bool final_output_ = true;
};
/**
* DenseTensorIterator: Used for preprocessing metadata of tensors
* participating in computation. Can be directly used as OffsetCalculator
* input parameter to assist with index calculations.
*/
struct DenseTensorIterator final : public DenseTensorIteratorBase {
DenseTensorIterator() : DenseTensorIteratorBase() {}
DenseTensorIterator(const DenseTensorIteratorBase& iter)
: DenseTensorIteratorBase(iter) {}
void set_output_raw_strided(int64_t output_idx,
std::vector<int64_t> sizes,
std::vector<int64_t> strides) override;
};
/**
* DenseTensorIteratorConfig: Used to configure tensors and computation rules
* for DenseTensorIterator
*
* This class configures the tensors participating in computation and the
* operation rules for DenseTensorIterator. Usage example:
*
* DenseTensorIteratorConfig config;
* // Add tensors participating in computation
* // Set whether to use specific methods in TensorIterator
* config.add_output(a);
* config.add_const_input(b);
* config.add_const_input(c);
*
* // Calculate the common broadcast shape and transformed strides for each
* dimension DenseTensorIterator iter = config.build();
*/
struct DenseTensorIteratorConfig final {
public:
friend struct DenseTensorIteratorBase;
friend struct DenseTensorIterator;
DenseTensorIteratorConfig() = default;
DenseTensorIteratorConfig(DenseTensorIteratorConfig&&) = default;
DenseTensorIteratorConfig& operator=(DenseTensorIteratorConfig&&) = default;
~DenseTensorIteratorConfig() = default;
DenseTensorIteratorConfig& add_output(const DenseTensor& output) {
return add_borrowed_output(output);
}
DenseTensorIteratorConfig& add_input(const DenseTensor& input) {
return add_borrowed_input(input);
}
DenseTensorIteratorConfig& add_const_input(const DenseTensor& input) {
return add_borrowed_const_input(input);
}
DenseTensorIteratorConfig& add_output(DenseTensor&& output) = delete;
DenseTensorIteratorConfig& add_input(DenseTensor&& input) = delete;
DenseTensorIteratorConfig& add_const_input(DenseTensor&& input) = delete;
DenseTensorIteratorConfig& add_borrowed_output(const DenseTensor& output);
DenseTensorIteratorConfig& add_borrowed_input(const DenseTensor& input);
DenseTensorIteratorConfig& add_borrowed_const_input(const DenseTensor& input);
DenseTensorIteratorConfig& add_borrowed_output(DenseTensor&& output) = delete;
DenseTensorIteratorConfig& add_borrowed_input(DenseTensor&& input) = delete;
DenseTensorIteratorConfig& add_borrowed_const_input(DenseTensor&& input) =
delete;
DenseTensorIteratorConfig& resize_outputs(bool resize_outputs) {
resize_outputs_ = resize_outputs;
return *this;
}
DenseTensorIteratorConfig& is_reduction(const bool _is_reduction) {
is_reduction_ = _is_reduction;
return *this;
}
DenseTensorIterator build() {
DenseTensorIterator iter;
iter.build(*this);
return iter;
}
bool is_alloc_out_ = false;
private:
std::vector<const DenseTensor*> tensors_;
std::vector<size_t> const_tensor_indices_;
size_t num_outputs_ = 0;
size_t num_inputs_ = 0;
std::optional<std::vector<int64_t>> static_shape_ = std::nullopt;
bool is_reduction_ = false;
bool resize_outputs_ = false;
};
struct DimIter {
DimIter(std::vector<int64_t> shape, int64_t start, int64_t end);
void iter_to_next(const std::array<int64_t, 2>& step);
bool iter_to_end() const;
std::array<int64_t, 2> iter_for_step() const;
std::vector<int64_t> shape;
int64_t start;
int64_t end;
paddle::small_vector<int64_t, 4> values;
int64_t offset;
};
struct Tensor32BitSplitter {
struct iterator {
iterator() = default;
explicit iterator(const DenseTensorIteratorBase& iter);
iterator(iterator&&) = default;
iterator& operator=(iterator&&) = default;
~iterator() = default;
DenseTensorIterator& operator*() const;
iterator& operator++();
bool operator==(const iterator& other) const {
return this == &other ||
(iterator_stack_.empty() && other.iterator_stack_.empty());
}
bool operator!=(const iterator& other) const { return !(*this == other); }
std::vector<std::unique_ptr<DenseTensorIterator>> iterator_stack_;
};
explicit Tensor32BitSplitter(const DenseTensorIteratorBase& iter)
: source_iterator_(iter) {}
iterator begin() const;
iterator end() const;
private:
const DenseTensorIteratorBase& source_iterator_;
};
} // namespace phi