Files
deeplearning4j--deeplearning4j/libnd4j/include/system/Environment.h
T
2026-07-13 12:47:05 +08:00

364 lines
13 KiB
C++

/* ******************************************************************************
*
*
* 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.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* 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
******************************************************************************/
//
// Created by raver119 on 06.10.2017.
//
#ifndef LIBND4J_ENVIRONMENT_H
#define LIBND4J_ENVIRONMENT_H
#include <array/DataType.h>
#include <types/pair.h>
#include <atomic>
#include <stdexcept>
#include <vector>
#include <config.h>
#ifdef SD_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#include "CudaLimitType.h"
#endif
namespace sd {
class SD_LIB_EXPORT Environment {
private:
std::atomic<int> _tadThreshold;
std::atomic<int> _elementThreshold;
std::atomic<bool> _verbose;
std::atomic<bool> _debug;
std::atomic<bool> _leaks;
std::atomic<bool> _profile;
std::atomic<sd::DataType> _dataType;
std::atomic<bool> _precBoost;
std::atomic<bool> _useONEDNN{true};
std::atomic<bool> _allowHelpers{true};
std::atomic<bool> funcTracePrintDeallocate;
std::atomic<bool> funcTracePrintAllocate;
// NDArray lifecycle tracking fields
// Prevents backward-cpp crashes during early JVM initialization
// Can be enabled via SD_LIFECYCLE_TRACKING=1 env var after JVM is ready
std::atomic<bool> _lifecycleTracking{false};
std::atomic<bool> _trackViews{true};
std::atomic<bool> _trackDeletions{true};
std::atomic<int> _stackDepth{32};
std::atomic<int> _reportInterval{300};
std::atomic<size_t> _maxDeletionHistory{10000};
std::atomic<bool> _snapshotFiles{false}; // Default off - only write snapshots on demand
std::atomic<bool> _trackOperations{false}; // Default off - operation tracking adds overhead
std::atomic<int> _maxThreads;
std::atomic<int> _maxMasterThreads;
std::atomic<bool> deleteSpecial{true};
std::atomic<bool> deletePrimary{true};
std::atomic<bool> deleteShapeInfo{true};
std::atomic<bool> _checkInputChange{false};
std::atomic<bool> _checkOutputChange{false};
std::atomic<bool> _logNDArrayEvenuts{false};
std::atomic<bool> _logNativeNDArrayCreation{false};
// these fields hold defaults
std::atomic<int64_t> _maxTotalPrimaryMemory{-1};
std::atomic<int64_t> _maxTotalSpecialMemory{-1};
std::atomic<int64_t> _maxDeviceMemory{-1};
bool _blasFallback = false;
std::atomic<bool> _enableBlasFall{true};
#ifdef SD_EXPERIMENTAL_ENABLED
const bool _experimental = true;
#else
const bool _experimental = false;
#endif
// device compute capability for CUDA
std::vector<Pair> _capabilities;
// CUDA specific environment configurations
std::atomic<int> _cudaDeviceCount{0};
std::atomic<int> _cudaCurrentDevice{0};
std::atomic<bool> _cudaMemoryPinned{false};
std::atomic<bool> _cudaUseManagedMemory{false};
std::atomic<int> _cudaMemoryPoolSize{0}; // in MB
std::atomic<bool> _cudaForceP2P{false};
std::atomic<bool> _cudaAllocatorEnabled{true};
std::atomic<int> _cudaMaxBlocks{0};
std::atomic<int> _cudaMaxThreadsPerBlock{0};
std::atomic<bool> _cudaAsyncExecution{true};
std::atomic<int> _cudaStreamLimit{4};
std::atomic<bool> _cudaUseDeviceHost{false};
std::atomic<int> _cudaEventLimit{4};
std::atomic<int> _cudaCachingAllocatorLimit{0}; // in MB
std::atomic<bool> _cudaUseUnifiedMemory{false};
std::atomic<int> _cudaPrefetchSize{0}; // in MB
std::atomic<bool> _cudaGraphOptimization{false};
std::atomic<bool> _cudaTensorCoreEnabled{true};
std::atomic<int> _cudaBlockingSync{0};
std::atomic<int> _cudaDeviceSchedule{0}; // 0: default, 1: spin, 2: yield, 3: block
// CUDA Device Limit configurations
std::atomic<size_t> _cudaStackSize{0}; // cudaLimitStackSize
std::atomic<size_t> _cudaMallocHeapSize{0}; // cudaLimitMallocHeapSize
std::atomic<size_t> _cudaPrintfFifoSize{0}; // cudaLimitPrintfFifoSize
std::atomic<size_t> _cudaDevRuntimeSyncDepth{0}; // cudaLimitDevRuntimeSyncDepth
std::atomic<size_t> _cudaDevRuntimePendingLaunchCount{0}; // cudaLimitDevRuntimePendingLaunchCount
std::atomic<size_t> _cudaMaxL2FetchGranularity{0}; // cudaLimitMaxL2FetchGranularity
std::atomic<size_t> _cudaPersistingL2CacheSize{0}; // cudaLimitPersistingL2CacheSize
Environment();
public:
~Environment();
/**
* These 3 fields are mostly for CUDA/cuBLAS version tracking
*/
int _blasMajorVersion = 0;
int _blasMinorVersion = 0;
int _blasPatchVersion = 0;
static Environment& getInstance();
bool isEnableBlas() {
return _enableBlasFall.load();
}
void setEnableBlas(bool reallyEnable) {
_enableBlasFall.store(reallyEnable);
}
/**
* When log ndarray evens is true in c++
* certain features of ndarray logging will trigger such as what ndarray constructors are being called.
* A great use case for this is for detecting subtle changes in ndarrays like move constructor calls
* which can cause the underlying data to change.
* @return
*/
bool isLogNativeNDArrayCreation();
void setLogNativeNDArrayCreation(bool logNativeNDArrayCreation);
/**
* This is mostly a java feature. We can use this to build a framework
* for logging ndarray events from c++ later.
* @return
*/
bool isLogNDArrayEvents();
void setLogNDArrayEvents(bool logNDArrayEvents);
/**
* This is mainly for debugging. This toggles
* deletion of shape info descriptors.
* This can be used to isolate potential issues with shape info
* memory management.
* The next concern is why have this at all?
* Historically, we had issues with shape descriptors and shape info
* buffers being deallocated when they shouldn't be due to stack based deallocation.
* By controlling everything with normal heap allocation, manual deletes and configurable behavior
* we can keep memory management consistent and predictable.
*/
bool isDeleteSpecial();
void setDeleteSpecial(bool reallyDelete);
bool isDeletePrimary();
void setDeletePrimary(bool reallyDelete);
/**
* Checks whether the outputs of the op have changed
* by duplicating them before and after the op runs
* if it doesn't change it throws an exception.
* @return
*/
bool isCheckOutputChange();
void setCheckOutputChange(bool reallyCheck);
/**
* Checks whether immutable ops changed their inputs by
* duplicating each input and ensuring they're still equal after the op runs.
* @return
*/
bool isCheckInputChange();
void setCheckInputChange(bool reallyCheck);
bool isVerbose();
void setVerbose(bool reallyVerbose);
bool isDebug();
bool isProfiling();
bool isDetectingLeaks();
bool isDebugAndVerbose();
void setDebug(bool reallyDebug);
void setProfiling(bool reallyProfile);
void setLeaksDetector(bool reallyDetect);
bool helpersAllowed();
void allowHelpers(bool reallyAllow);
bool blasFallback();
int tadThreshold();
void setTadThreshold(int threshold);
int elementwiseThreshold();
void setElementwiseThreshold(int threshold);
int maxThreads();
void setMaxThreads(int max);
int maxMasterThreads();
void setMaxMasterThreads(int max);
/*
* Legacy memory limits API, still used in new API as simplified version
*/
void setMaxPrimaryMemory(uint64_t maxBytes);
void setMaxSpecialyMemory(uint64_t maxBytes);
void setMaxDeviceMemory(uint64_t maxBytes);
uint64_t maxPrimaryMemory();
uint64_t maxSpecialMemory();
////////////////////////
/*
* Methods for memory limits/counters
*/
void setGroupLimit(int group, sd::LongType numBytes);
void setDeviceLimit(int deviceId, sd::LongType numBytes);
sd::LongType getGroupLimit(int group);
sd::LongType getDeviceLimit(int deviceId);
sd::LongType getGroupCounter(int group);
sd::LongType getDeviceCounter(int deviceId);
////////////////////////
bool isUseONEDNN() { return _useONEDNN.load(); }
void setUseONEDNN(bool useMKLDNN) { _useONEDNN.store(useMKLDNN); }
sd::DataType defaultFloatDataType();
void setDefaultFloatDataType(sd::DataType dtype);
bool precisionBoostAllowed();
void allowPrecisionBoost(bool reallyAllow);
bool isExperimentalBuild();
bool isCPU();
int blasMajorVersion();
int blasMinorVersion();
int blasPatchVersion();
std::vector<Pair>& capabilities();
bool isFuncTracePrintDeallocate();
void setFuncTracePrintDeallocate(bool reallyPrint);
bool isFuncTracePrintAllocate();
void setFuncTracePrintAllocate(bool reallyPrint);
// NDArray lifecycle tracking methods
bool isLifecycleTracking();
void setLifecycleTracking(bool enabled);
bool isTrackViews();
void setTrackViews(bool track);
bool isTrackDeletions();
void setTrackDeletions(bool track);
int getStackDepth();
void setStackDepth(int depth);
int getReportInterval();
void setReportInterval(int seconds);
size_t getMaxDeletionHistory();
void setMaxDeletionHistory(size_t max);
bool isSnapshotFiles();
void setSnapshotFiles(bool enabled);
bool isTrackOperations();
void setTrackOperations(bool enabled);
bool isDeleteShapeInfo();
void setDeleteShapeInfo(bool deleteShapeInfo);
// CUDA specific getters/setters
int cudaDeviceCount() { return _cudaDeviceCount.load(); }
int cudaCurrentDevice() { return _cudaCurrentDevice.load(); }
void setCudaCurrentDevice(int device);
bool cudaMemoryPinned() { return _cudaMemoryPinned.load(); }
void setCudaMemoryPinned(bool pinned);
bool cudaUseManagedMemory() { return _cudaUseManagedMemory.load(); }
void setCudaUseManagedMemory(bool managed);
int cudaMemoryPoolSize() { return _cudaMemoryPoolSize.load(); }
void setCudaMemoryPoolSize(int sizeInMB);
bool cudaForceP2P() { return _cudaForceP2P.load(); }
void setCudaForceP2P(bool forceP2P);
bool cudaAllocatorEnabled() { return _cudaAllocatorEnabled.load(); }
void setCudaAllocatorEnabled(bool enabled);
int cudaMaxBlocks() { return _cudaMaxBlocks.load(); }
void setCudaMaxBlocks(int blocks);
int cudaMaxThreadsPerBlock() { return _cudaMaxThreadsPerBlock.load(); }
void setCudaMaxThreadsPerBlock(int threads);
bool cudaAsyncExecution() { return _cudaAsyncExecution.load(); }
void setCudaAsyncExecution(bool async);
int cudaStreamLimit() { return _cudaStreamLimit.load(); }
void setCudaStreamLimit(int limit);
bool cudaUseDeviceHost() { return _cudaUseDeviceHost.load(); }
void setCudaUseDeviceHost(bool useDeviceHost);
int cudaEventLimit() { return _cudaEventLimit.load(); }
void setCudaEventLimit(int limit);
int cudaCachingAllocatorLimit() { return _cudaCachingAllocatorLimit.load(); }
void setCudaCachingAllocatorLimit(int limitInMB);
bool cudaUseUnifiedMemory() { return _cudaUseUnifiedMemory.load(); }
void setCudaUseUnifiedMemory(bool unified);
int cudaPrefetchSize() { return _cudaPrefetchSize.load(); }
void setCudaPrefetchSize(int sizeInMB);
bool cudaGraphOptimization() { return _cudaGraphOptimization.load(); }
void setCudaGraphOptimization(bool enabled);
bool cudaTensorCoreEnabled() { return _cudaTensorCoreEnabled.load(); }
void setCudaTensorCoreEnabled(bool enabled);
int cudaBlockingSync() { return _cudaBlockingSync.load(); }
void setCudaBlockingSync(int mode);
int cudaDeviceSchedule() { return _cudaDeviceSchedule.load(); }
void setCudaDeviceSchedule(int schedule);
// CUDA Device Limit getters/setters
size_t cudaStackSize() { return _cudaStackSize.load(); }
void setCudaStackSize(size_t size);
size_t cudaMallocHeapSize() { return _cudaMallocHeapSize.load(); }
void setCudaMallocHeapSize(size_t size);
size_t cudaPrintfFifoSize() { return _cudaPrintfFifoSize.load(); }
void setCudaPrintfFifoSize(size_t size);
size_t cudaDevRuntimeSyncDepth() { return _cudaDevRuntimeSyncDepth.load(); }
void setCudaDevRuntimeSyncDepth(size_t depth);
size_t cudaDevRuntimePendingLaunchCount() { return _cudaDevRuntimePendingLaunchCount.load(); }
void setCudaDevRuntimePendingLaunchCount(size_t count);
size_t cudaMaxL2FetchGranularity() { return _cudaMaxL2FetchGranularity.load(); }
void setCudaMaxL2FetchGranularity(size_t size);
size_t cudaPersistingL2CacheSize() { return _cudaPersistingL2CacheSize.load(); }
void setCudaPersistingL2CacheSize(size_t size);
bool setCudaDeviceLimit(int limitType, size_t value);
// Initialize CUDA environment settings from environment variables
void initCudaEnvironment();
// Initialize CUDA device limits from environment variables
void initCudaDeviceLimits();
};
} // namespace sd
#endif // LIBND4J_ENVIRONMENT_H