Files
deeplearning4j--deeplearning4j/libnd4j/include/helpers/impl/ConstantTadHelper.cpp
T
2026-07-13 12:47:05 +08:00

140 lines
4.6 KiB
C++

/* ******************************************************************************
*
* Copyright (c) 2024 Konduit K.K.
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://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.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#include <array/TadDescriptor.h>
#include <array/TadPack.h>
#include <helpers/ConstantTadHelper.h>
#include <helpers/ShapeUtils.h>
namespace sd {
ConstantTadHelper& ConstantTadHelper::getInstance() {
static ConstantTadHelper instance;
return instance;
}
std::shared_ptr<TadPack> ConstantTadHelper::tadForDimensions(LongType* originalShape, LongType dimension) {
return tadForDimensions(originalShape, &dimension, 1);
}
std::shared_ptr<TadPack> ConstantTadHelper::tadForDimensions(LongType* originalShape, std::vector<LongType>* dimensions) {
if (dimensions == nullptr) {
THROW_EXCEPTION("Dimensions vector is null");
}
return tadForDimensions(originalShape, const_cast<LongType*>(dimensions->data()), dimensions->size());
}
std::shared_ptr<TadPack> ConstantTadHelper::tadForDimensions(TadDescriptor* descriptor) {
if (descriptor == nullptr) {
THROW_EXCEPTION("TadDescriptor is null");
}
return tadForDimensions(descriptor->originalShape(), descriptor->axis().data(),
descriptor->axis().size());
}
std::shared_ptr<TadPack> ConstantTadHelper::tadForDimensions(LongType* originalShape, LongType* dimensions, LongType dimLength) {
if (originalShape == nullptr) {
THROW_EXCEPTION("Original shape is null");
}
if (dimensions == nullptr && dimLength > 0) {
THROW_EXCEPTION("Dimensions array is null but dimLength > 0");
}
// Check for empty array
if (shape::isEmptyConst(originalShape)) {
THROW_EXCEPTION("Cannot create TADs for empty array");
}
sd::LongType rank = shape::rank(originalShape);
if (rank < 0) {
THROW_EXCEPTION("Invalid shape rank");
}
// Check for zero-sized dimensions
for (LongType i = 0; i < rank; i++) {
if (shape::sizeAt(originalShape, i) == 0) {
THROW_EXCEPTION("Cannot create TADs for array with zero-sized dimensions");
}
}
// Handle zero dimension length case - treat entire array as single TAD
if (dimLength <= 0) {
// When no dimensions specified, create TAD along all dimensions
// This means the entire array is treated as a single TAD
std::vector<LongType> allDims;
for (LongType i = 0; i < rank; i++) {
allDims.push_back(i);
}
// Recursively call with all dimensions
return tadForDimensions(originalShape, allDims.data(), rank);
}
// Additional validation: check if dimensions are within valid range
for (LongType i = 0; i < dimLength; i++) {
LongType dim = dimensions[i];
if (dim < 0) dim += rank; // Handle negative dimensions
if (dim < 0 || dim >= rank) {
THROW_EXCEPTION("Dimension index is out of bounds");
}
}
// Create non-temporary vector to satisfy the reference requirement
std::vector<LongType> dims(dimensions, dimensions + dimLength);
// The shared_ptr keeps the TadPack alive even if the cache tries to clear it
std::shared_ptr<TadPack> result = nullptr;
try {
result = _trie.getOrCreate(dims, originalShape);
} catch (const std::exception& e) {
THROW_EXCEPTION("Failed to create or retrieve TAD pack");
}
// DO NOT call checkAndCleanupCaches() here - would delete the pack we just created!
// Cleanup happens at NativeOps layer AFTER operations complete.
return result;
}
void ConstantTadHelper::clearCache() {
_trie.clear();
}
LongType ConstantTadHelper::getCachedEntries() const {
return _trie.getCachedEntries();
}
LongType ConstantTadHelper::getCachedBytes() const {
return _trie.getCachedBytes();
}
LongType ConstantTadHelper::getPeakCachedEntries() const {
return _trie.getPeakCachedEntries();
}
LongType ConstantTadHelper::getPeakCachedBytes() const {
return _trie.getPeakCachedBytes();
}
std::string ConstantTadHelper::toString(int maxDepth, int maxEntries) const {
return _trie.toString(maxDepth, maxEntries);
}
void ConstantTadHelper::getCachedPointers(std::unordered_set<void*>& out_pointers) const {
_trie.getCachedPointers(out_pointers);
}
} // namespace sd