/* ****************************************************************************** * * * 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 agibsonccc on 2/21/16. // #define __STDC_CONSTANT_MACROS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef _WIN32 #include #include #else #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CPU_FEATURES #include #endif #include #include #include //these are mainly for cuda sd::Pointer lcScalarPointer(OpaqueLaunchContext lc) { return nullptr; } sd::Pointer lcReductionPointer(OpaqueLaunchContext lc) { return nullptr; } sd::Pointer lcAllocationPointer(OpaqueLaunchContext lc) { return nullptr; } sd::Pointer lcExecutionStream(OpaqueLaunchContext lc) { return nullptr; } sd::Pointer lcCopyStream(OpaqueLaunchContext lc) { return nullptr; } sd::Pointer lcBlasHandle(OpaqueLaunchContext lc) { return nullptr; } sd::Pointer lcSolverHandle(OpaqueLaunchContext lc) { return nullptr; } void execBroadcastBool(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,OpaqueNDArray y, OpaqueNDArray z,void *extraParams, OpaqueNDArray dimension) { auto tadPackX = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto tadPackZ = sd::ConstantTadHelper::getInstance().tadForDimensions(z->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto hTADShapeInfo = tadPackX->primaryShapeInfo(); auto hTADOffsets = tadPackX->primaryOffsets(); auto hTADShapeInfoZ = tadPackZ->primaryShapeInfo(); auto hTADOffsetsZ = tadPackZ->primaryOffsets(); sd::NDArray::prepareSpecialUse({z}, {x, y}); NativeOpExecutioner::execBroadcastBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams, dimension->bufferAsT(), dimension->lengthOf(), hTADShapeInfo, hTADOffsets, hTADShapeInfoZ, hTADOffsetsZ); sd::NDArray::registerSpecialUse({z}, {x, y}); } /** * * @param opNum * @param hX * @param hXShapeInfo * @param extraParamsVals * @param hY * @param hYShapeInfo * @param hZ * @param hZShapeInfo */ void execReduce3(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams,OpaqueNDArray y, OpaqueNDArray z) { #ifdef __cpp_exceptions try { auto dbX = x->dataBuffer(); auto dbY = y->dataBuffer(); auto dbZ = z->dataBuffer(); x->preparePrimaryUse({z}, {x,y}); NativeOpExecutioner::execReduce3(nullptr, opNum, dbX != nullptr ? x->buffer() : nullptr, x->shapeInfo(), dbX != nullptr ? dbX->special() : nullptr, x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), dbZ != nullptr ? dbZ->primary() : nullptr, z->shapeInfo(), dbZ != nullptr ? z->specialBuffer() : nullptr, z->specialShapeInfo()); x->registerPrimaryUse({z}, {x,y}); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto dbX = x->dataBuffer(); auto dbY = y->dataBuffer(); auto dbZ = z->dataBuffer(); x->preparePrimaryUse({z}, {x,y}); NativeOpExecutioner::execReduce3(nullptr, opNum, dbX != nullptr ? x->buffer() : nullptr, x->shapeInfo(), dbX != nullptr ? dbX->special() : nullptr, x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), dbZ != nullptr ? dbZ->primary() : nullptr, z->shapeInfo(), dbZ != nullptr ? z->specialBuffer() : nullptr, z->specialShapeInfo()); x->registerPrimaryUse({z}, {x,y}); #endif } /** * * @param opNum * @param hX * @param hXShapeInfo * @param extraParamsVals * @param hY * @param hYShapeInfo */ void execReduce3Scalar(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams ,OpaqueNDArray y, OpaqueNDArray z) { #ifdef __cpp_exceptions try { auto dbX = x->dataBuffer(); auto dbY = y->dataBuffer(); auto dbZ = z->dataBuffer(); x->preparePrimaryUse({z}, {x, y}); NativeOpExecutioner::execReduce3Scalar(nullptr, opNum, dbX != nullptr ? x->buffer() : nullptr, x->shapeInfo(), dbX != nullptr ? x->specialBuffer() : nullptr, x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), dbY->special(), y->specialShapeInfo(), dbZ != nullptr ? z->buffer() : nullptr, z->shapeInfo(), dbZ != nullptr ? dbZ->special() : nullptr, z->specialShapeInfo()); x->registerPrimaryUse({z}, {x, y}); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto dbX = x->dataBuffer(); auto dbY = y->dataBuffer(); auto dbZ = z->dataBuffer(); x->preparePrimaryUse({z}, {x, y}); NativeOpExecutioner::execReduce3Scalar(nullptr, opNum, dbX != nullptr ? x->buffer() : nullptr, x->shapeInfo(), dbX != nullptr ? x->specialBuffer() : nullptr, x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), dbY->special(), y->specialShapeInfo(), dbZ != nullptr ? z->buffer() : nullptr, z->shapeInfo(), dbZ != nullptr ? dbZ->special() : nullptr, z->specialShapeInfo()); x->registerPrimaryUse({z}, {x, y}); #endif } bool isBlasVersionMatches(int major, int minor, int build) { return true; } /** * This is dummy method for JNI compatibility * Since we'll use this from java, jni compiler would like to have method no matter what. */ void initializeDevicesAndFunctions() {} /** * Initialize the shape cache early to prevent race conditions during static initialization. * This ensures ConstantShapeHelper and its internal DirectShapeTrie are fully initialized * before any multi-threaded access occurs. * * Safe to call multiple times - subsequent calls are no-ops. */ void initializeShapeCache() { sd::ConstantShapeHelper::initializeEarly(); } /** * Initialize the TAD (Tensor-Along-Dimension) cache early to prevent race conditions. * This ensures ConstantTadHelper and its internal DirectTadTrie are fully initialized * before any multi-threaded access occurs. * * Safe to call multiple times - subsequent calls are no-ops. */ void initializeTadCache() { sd::ConstantTadHelper::getInstance(); } void initializeFunctions(sd::Pointer *functions) { sd::BlasHelper::getInstance().initializeFunctions(functions); } /** * This method acquires memory chunk of requested size on host side * * @param sd::Pointer sd::Pointer that'll be used for allocation * @param memorySize memory size, in bytes * @param flags optional parameter */ sd::Pointer mallocHost(sd::LongType memorySize, int flags) { #if defined(SD_ALIGNED_ALLOC) return static_cast( aligned_alloc(SD_DESIRED_ALIGNMENT, (memorySize + SD_DESIRED_ALIGNMENT - 1) & (-SD_DESIRED_ALIGNMENT))); #else return reinterpret_cast(new int8_t[memorySize]); #endif } /** * This method acquires memory chunk of requested size on specified device * * PLEASE NOTE: This method is NOT supported and has NO effect in CPU-based backend. * * @param sd::Pointer sd::Pointer that'll be used for allocation * @param memorySize memory size, in bytes * @param ptrToDeviceId sd::Pointer to deviceId. For cuda that's just and int, for OpenCL that's sd::Pointer to device_id, etc * @param flags optional parameter */ sd::Pointer mallocDevice(sd::LongType memorySize, int deviceId, int flags) { // not supported return 0L; } /** * This method releases previously allocated host memory space * * @param sd::Pointer sd::Pointer that'll be freed */ int freeHost(sd::Pointer pointer) { #if defined(SD_ALIGNED_ALLOC) free(pointer); #else delete[] reinterpret_cast(pointer); #endif return 1L; } /** * This method releases previously allocated memory space on device * * PLEASE NOTE: This method is NOT supported and has NO effect in CPU-based backend. * * @param sd::Pointer sd::Pointer that'll be freed * @param ptrToDeviceId sd::Pointer to deviceId. */ int freeDevice(sd::Pointer pointer, int deviceId) { // not supported return 0L; } /** * Returns the maximum number open mp threads */ int ompGetMaxThreads() { return omp_get_max_threads(); } /** * Returns the number open mp threads */ int ompGetNumThreads() { return omp_get_num_threads(); } /** * Sets the number of openmp threads */ void setOmpNumThreads(int threads) { omp_set_num_threads(threads); } /** * Sets the number of threads used by OpenBLAS for BLAS operations. * This is separate from OMP threads and specifically controls OpenBLAS's internal threading. * Default should be 1 to prevent TLS corruption crashes in multi-threaded Java applications. */ void setOpenBlasThreads(int threads) { #if defined(__OPENBLAS) openblas_set_num_threads(threads); #elif defined(__MKL) // MKL uses a different function MKL_Set_Num_Threads(threads); #else // No OpenBLAS or MKL - this is a no-op // The OMP thread setting may still affect BLAS behavior in some configurations #endif // Also update the Environment setting sd::Environment::getInstance().setOpenBlasThreads(threads); } /** * Gets the number of threads OpenBLAS is configured to use. */ int getOpenBlasThreads() { return sd::Environment::getInstance().getOpenBlasThreads(); } /** * Check if BLAS call serialization is enabled. */ bool isSerializeBlasCalls() { return sd::Environment::getInstance().isSerializeBlasCalls(); } /** * Enable or disable BLAS call serialization. */ void setSerializeBlasCalls(bool serialize) { sd::Environment::getInstance().setSerializeBlasCalls(serialize); } sd::Pointer createContext() { return 0L; } sd::Pointer createStream() { return 0L; } sd::Pointer createEvent() { return 0L; } int getDeviceBlockThreshold(int deviceId) { return 0; } int getDeviceMajor(int deviceId) { return 0; } int getDeviceSharedThreshold(int deviceId) {return 0; } int getDeviceMinor(int deviceId) { return 0; } int getDeviceId(void* deviceId) { return 0; } int registerEvent(sd::Pointer event, sd::Pointer stream) { return 0L; } int setDevice(int deviceId) { return 0L; } sd::LongType getDeviceFreeMemory(int deviceId) { return 0L; } sd::LongType getDeviceFreeMemoryDefault() { return 0L; } sd::LongType getDeviceTotalMemory(int deviceId) { return 0L; } int memcpySync(sd::Pointer dst, sd::Pointer src, sd::LongType size, int flags, sd::Pointer reserved) { return 0L; } int memcpyAsync(sd::Pointer dst, sd::Pointer src, sd::LongType size, int flags, sd::Pointer reserved) { return 0L; } int memsetSync(sd::Pointer dst, int value, sd::LongType size, int flags, sd::Pointer reserved) { return 0L; } int memsetAsync(sd::Pointer dst, int value, sd::LongType size, int flags, sd::Pointer reserved) { return 0L; } int destroyEvent(sd::Pointer event) { return 0L; } int streamSynchronize(sd::Pointer stream) { return 0L; } int eventSynchronize(sd::Pointer event) { return 0L; } int getAvailableDevices() { return 0L; } void enableDebugMode(bool reallyEnable) { sd::Environment::getInstance().setDebug(reallyEnable); } void enableVerboseMode(bool reallyEnable) { sd::Environment::getInstance().setVerbose(reallyEnable); } void setGridLimit(int gridSize) { // no-op } void prescanArrayRecursive(sd::Pointer *extras, int *dZ, int *dX, int numElements, int level) { THROW_EXCEPTION("prescanArrayRecursive Not implemented"); } int memcpyConstantAsync(sd::LongType dst, sd::Pointer src, sd::LongType size, int flags, sd::Pointer reserved) { // no-op return 0L; } sd::Pointer getConstantSpace() { // no-op return 0L; } template void pullRowsGeneric(OpaqueNDArray vx, OpaqueNDArray vz, const int n, OpaqueNDArray indexes, sd::LongType dimension) { auto hX = vx->bufferAsT(); auto hZ = vz->bufferAsT(); auto hXShapeInfo = vx->shapeInfo(); auto hZShapeInfo = vz->shapeInfo(); auto tadPackX = sd::ConstantTadHelper::getInstance().tadForDimensions(hXShapeInfo, &dimension, 1); auto tadPackZ = sd::ConstantTadHelper::getInstance().tadForDimensions(hZShapeInfo, &dimension, 1); auto tadShapeInfo = tadPackX->primaryShapeInfo(); auto tadOffsets = tadPackX->primaryOffsets(); auto zTadShapeInfo = tadPackZ->primaryShapeInfo(); auto zTadOffsets = tadPackZ->primaryOffsets(); const auto tadLength = shape::length(tadShapeInfo); int elementsPerThread = n / TAD_THRESHOLD; int _threads = sd::math::sd_max(1, elementsPerThread); _threads = sd::math::sd_min(_threads, sd::Environment::getInstance().maxThreads()); sd::LongType tadRank = shape::rank(tadShapeInfo); sd::LongType *tadShape = shape::shapeOf(tadShapeInfo); sd::LongType *tadStride = shape::stride(tadShapeInfo); sd::LongType zTadRank = shape::rank(zTadShapeInfo); sd::LongType *zTadShape = shape::shapeOf(zTadShapeInfo); sd::LongType *zTadStride = shape::stride(zTadShapeInfo); auto func = PRAGMA_THREADS_FOR { for (auto idx2 = start; idx2 < stop; idx2++) { auto xTadOffsetForBlock = tadOffsets[reinterpret_cast(indexes->buffer())[idx2]]; auto zTadOffsetForBlock = zTadOffsets[idx2]; auto rX = hX + xTadOffsetForBlock; auto rZ = hZ + zTadOffsetForBlock; sd::LongType xCoords[SD_MAX_RANK]; sd::LongType zCoords[SD_MAX_RANK]; sd::LongType xOffset; sd::LongType zOffset; INDEX2COORDS(idx2, tadRank, tadShape, xCoords); COORDS2INDEX(tadRank, tadStride, xCoords, xOffset); INDEX2COORDS(idx2, zTadRank,zTadShape, zCoords); COORDS2INDEX(zTadRank, zTadStride, zCoords, zOffset); for (sd::LongType i = 0; i < tadLength; i++) { hZ[zOffset + i] = hX[xOffset + i]; } } }; samediff::Threads::parallel_tad(func, 0, n, 1, _threads); } void tryPointer(sd::Pointer extra, sd::Pointer p, int len) { #ifdef __cpp_exceptions try { auto buf = reinterpret_cast(p); int cnt = 0; for (int i = 0; i < len; i++) cnt += buf[cnt]; } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto buf = reinterpret_cast(p); int cnt = 0; for (int i = 0; i < len; i++) cnt += buf[cnt]; #endif } void pullRows(sd::Pointer *extraPointers, OpaqueNDArray x, OpaqueNDArray z, sd::LongType n, OpaqueNDArray indexes, sd::LongType dimension) { #ifdef __cpp_exceptions try { auto xType = sd::ArrayOptions::dataType(x->shapeInfo()); BUILD_SINGLE_SELECTOR(xType, pullRowsGeneric, (x, z, n, indexes, dimension), SD_COMMON_TYPES); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto xType = sd::ArrayOptions::dataType(x->shapeInfo()); BUILD_SINGLE_SELECTOR(xType, pullRowsGeneric, (x, z, n, indexes, dimension), SD_COMMON_TYPES); #endif } template void tearGeneric(void *vx, sd::LongType const *hXShapeInfo, sd::Pointer *targets, sd::LongType const *hZShapeInfo, sd::LongType const *tadShapeInfo, sd::LongType const *tadOffsets) { auto hX = reinterpret_cast(vx); const auto tadLength = shape::length(tadShapeInfo); auto numTads = shape::length(hXShapeInfo) / tadLength; sd::LongType tadRank = shape::rank(tadShapeInfo); sd::LongType *tadShape = shape::shapeOf(tadShapeInfo); sd::LongType *tadStride = shape::stride(tadShapeInfo); sd::LongType zTadRank = shape::rank(hZShapeInfo); sd::LongType *zTadShape = shape::shapeOf(hZShapeInfo); sd::LongType *zTadStride = shape::stride(hZShapeInfo); auto func = PRAGMA_THREADS_FOR { for (auto i = start; i < stop; i++) { auto hZ = reinterpret_cast(targets[i]); auto s = hX + tadOffsets[i]; for (sd::LongType j = 0; j < tadLength; j++) { sd::LongType xCoords[SD_MAX_RANK]; sd::LongType zCoords[SD_MAX_RANK]; sd::LongType xOffset; sd::LongType zOffset; INDEX2COORDS(j, tadRank, tadShape, xCoords); COORDS2INDEX(tadRank, zTadStride, xCoords, xOffset); INDEX2COORDS(j, zTadRank, zTadStride, zCoords); COORDS2INDEX(zTadRank, zTadStride, zCoords, zOffset); hZ[zOffset] = s[xOffset]; } } }; samediff::Threads::parallel_tad(func, 0, numTads); } void tear(sd::Pointer *extraPointers, OpaqueDataBuffer *dbX, sd::LongType const *hXShapeInfo, sd::LongType const *dXShapeInfo, sd::Pointer *targets, sd::LongType const *hZShapeInfo, sd::LongType const *tadShapeInfo, sd::LongType const *tadOffsets) { #ifdef __cpp_exceptions try { auto xType = sd::ArrayOptions::dataType(hXShapeInfo); BUILD_SINGLE_SELECTOR(xType, tearGeneric, (dbX != nullptr ? dbX->primary() : nullptr, hXShapeInfo, targets, hZShapeInfo, tadShapeInfo, tadOffsets), SD_COMMON_TYPES); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto xType = sd::ArrayOptions::dataType(hXShapeInfo); BUILD_SINGLE_SELECTOR(xType, tearGeneric, (dbX != nullptr ? dbX->primary() : nullptr, hXShapeInfo, targets, hZShapeInfo, tadShapeInfo, tadOffsets), SD_COMMON_TYPES); #endif } void enableP2P(bool enable) { // no-op } bool isP2PAvailable() { // always TRUE for cpu backend return true; } void checkP2P() { // no-op } template void shuffleGeneric(OpaqueNDArrayArr hX, OpaqueNDArrayArr hZ, int N, int *shuffleMap, sd::LongType *dimension, sd::LongType dimensionLength) { auto func = PRAGMA_THREADS_FOR { for (auto f = start; f < stop; f++) { T *hX2 = hX[f]->bufferAsT(); T *hZ2 = hZ[f]->bufferAsT(); auto xShapeInfo = hX[f]->shapeInfo(); auto zShapeInfo = hZ[f]->shapeInfo(); auto tadPackX = sd::ConstantTadHelper::getInstance().tadForDimensions(xShapeInfo, dimension, dimensionLength); auto tadPackZ = sd::ConstantTadHelper::getInstance().tadForDimensions(zShapeInfo, dimension, dimensionLength); auto tadOnlyShapeInfoX = tadPackX->primaryShapeInfo(); auto tadOffsetsX = tadPackX->primaryOffsets(); auto tadOnlyShapeInfoZ = tadPackZ->primaryShapeInfo(); auto tadOffsetsZ = tadPackZ->primaryOffsets(); const auto tadLength = shape::length(tadOnlyShapeInfoX); auto numTads = shape::length(xShapeInfo) / tadLength; sd::LongType xRank = shape::rank(xShapeInfo); sd::LongType zRank = shape::rank(zShapeInfo); sd::LongType *xShape = shape::shapeOf(xShapeInfo); sd::LongType *xStride = shape::stride(xShapeInfo); sd::LongType *zShape = shape::shapeOf(zShapeInfo); sd::LongType *zStride = shape::stride(zShapeInfo); if (shape::rank(xShapeInfo) == 1) { auto xLength = shape::length(xShapeInfo); for (sd::LongType r = 0; r < xLength; r++) { auto swapIdx = shuffleMap[r]; if (swapIdx < 0) continue; sd::LongType xCoords[SD_MAX_RANK]; sd::LongType zCoords[SD_MAX_RANK]; sd::LongType xOffset; sd::LongType zOffset; INDEX2COORDS(r, xRank, xShape, xCoords); COORDS2INDEX(xRank, xStride, xCoords, xOffset); INDEX2COORDS(swapIdx,zRank, zShape, zCoords); COORDS2INDEX(zRank, zStride, zCoords, zOffset); sd::math::sd_swap(hX2[xOffset], hZ2[zOffset]); } } else { sd::LongType tadShapeInfoRank = shape::rank(tadOnlyShapeInfoX); sd::LongType *tadShapeInfoShape = shape::shapeOf(tadOnlyShapeInfoX); sd::LongType *tadShapeInfoStride = shape::stride(tadOnlyShapeInfoX); sd::LongType zTadShapeInfoRank = shape::rank(tadOnlyShapeInfoZ); sd::LongType *zTadShapeInfoShape = shape::shapeOf(tadOnlyShapeInfoZ); sd::LongType *zTadShapeInfoStride = shape::stride(tadOnlyShapeInfoZ); for (sd::LongType r = 0; r < numTads; r++) { if (shuffleMap[r] < 0) continue; auto oldOffsetX = tadOffsetsX[r]; auto newOffsetZ = tadOffsetsZ[shuffleMap[r]]; auto rX = hX2 + oldOffsetX; auto rZ = hZ2 + newOffsetZ; for (sd::LongType i = 0; i < tadLength; i++) { sd::LongType xCoords[SD_MAX_RANK]; sd::LongType zCoords[SD_MAX_RANK]; sd::LongType xOffset; sd::LongType zOffset; INDEX2COORDS(i, tadShapeInfoRank, tadShapeInfoShape, xCoords); COORDS2INDEX(tadShapeInfoRank,tadShapeInfoStride, xCoords, xOffset); INDEX2COORDS(i, zTadShapeInfoRank,zTadShapeInfoShape, zCoords); COORDS2INDEX(zTadShapeInfoRank, zTadShapeInfoStride, zCoords, zOffset); sd::math::sd_swap(rX[xOffset], rZ[zOffset]); } } } } }; samediff::Threads::parallel_tad(func, 0, N); } void shuffle(sd::Pointer *extras, OpaqueNDArrayArr x, OpaqueNDArrayArr z, int N, OpaqueNDArray dimension, OpaqueNDArray shuffleMap) { #ifdef __cpp_exceptions try { auto dimensionData = reinterpret_cast(dimension->buffer()); auto dimensionLength = shape::length(dimension->shapeInfo()); auto xType = sd::ArrayOptions::dataType(x[0]->shapeInfo()); BUILD_SINGLE_SELECTOR(xType, shuffleGeneric, (x, z, N, reinterpret_cast(shuffleMap->buffer()), dimensionData, dimensionLength), SD_COMMON_TYPES); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto dimensionData = reinterpret_cast(dimension->buffer()); auto dimensionLength = shape::length(dimension->shapeInfo()); auto xType = sd::ArrayOptions::dataType(x[0]->shapeInfo()); BUILD_SINGLE_SELECTOR(xType, shuffleGeneric, (x, z, N, reinterpret_cast(shuffleMap->buffer()), dimensionData, dimensionLength), SD_COMMON_TYPES); #endif } bool isExperimentalEnabled() { return sd::Environment::getInstance().isExperimentalBuild(); } void setOmpMinThreads(int threads) { // TODO: to be implemented } int getDevice() { return 0; } char *name; bool nameSet = false; const char *getDeviceName(int deviceId) { #ifdef __cpp_exceptions try { if (!nameSet) { name = reinterpret_cast(malloc(256 * sizeof(char))); CHECK_ALLOC(name, "Failed to allocate new string buffer", 256); std::memset(name, 0, 256 * sizeof(char)); nameSet = true; // TODO: provide proper CPU model name here sprintf(name, "x86-compatible CPU"); } } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else if (!nameSet) { name = reinterpret_cast(malloc(256 * sizeof(char))); CHECK_ALLOC(name, "Failed to allocate new string buffer", 256); std::memset(name, 0, 256 * sizeof(char)); nameSet = true; // TODO: provide proper CPU model name here sprintf(name, "x86-compatible CPU"); } #endif return name; } void execRandom(sd::Pointer *extraPointers, int opNum, sd::Pointer state, OpaqueDataBuffer *dbZ, const sd::LongType *hZShapeInfo, const sd::LongType *dZShapeInfo, void *extraArguments) { #ifdef __cpp_exceptions try { OpaqueDataBuffer::preparePrimaryUse({dbZ}, {}); NativeOpExecutioner::execRandom(nullptr, opNum, state, dbZ != nullptr ? dbZ->primary() : nullptr, hZShapeInfo, dbZ != nullptr ? dbZ->special() : nullptr, dZShapeInfo, extraArguments); OpaqueDataBuffer::registerPrimaryUse({dbZ}, {}); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else OpaqueDataBuffer::preparePrimaryUse({dbZ}, {}); NativeOpExecutioner::execRandom(nullptr, opNum, state, dbZ != nullptr ? dbZ->primary() : nullptr, hZShapeInfo, dbZ != nullptr ? dbZ->special() : nullptr, dZShapeInfo, extraArguments); OpaqueDataBuffer::registerPrimaryUse({dbZ}, {}); #endif } void execRandom3(sd::Pointer *extraPointers, int opNum, sd::Pointer state, OpaqueDataBuffer *dbX, const sd::LongType *hXShapeInfo, const sd::LongType *dXShapeInfo, OpaqueDataBuffer *dbY, const sd::LongType *hYShapeInfo, const sd::LongType *dYShapeInfo, OpaqueDataBuffer *dbZ, const sd::LongType *hZShapeInfo, const sd::LongType *dZShapeInfo, void *extraArguments) { #ifdef __cpp_exceptions try { OpaqueDataBuffer::preparePrimaryUse({dbZ}, {dbX, dbY}); NativeOpExecutioner::execRandom(nullptr, opNum, state, dbX != nullptr ? dbX->primary() : nullptr, hXShapeInfo, dbX != nullptr ? dbX->special() : nullptr, dXShapeInfo, dbY->primary(), hYShapeInfo, dbY->special(), dYShapeInfo, dbZ != nullptr ? dbZ->primary() : nullptr, hZShapeInfo, dbZ != nullptr ? dbZ->special() : nullptr, dZShapeInfo, extraArguments); OpaqueDataBuffer::registerPrimaryUse({dbZ}, {dbX, dbY}); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else OpaqueDataBuffer::preparePrimaryUse({dbZ}, {dbX, dbY}); NativeOpExecutioner::execRandom(nullptr, opNum, state, dbX != nullptr ? dbX->primary() : nullptr, hXShapeInfo, dbX != nullptr ? dbX->special() : nullptr, dXShapeInfo, dbY->primary(), hYShapeInfo, dbY->special(), dYShapeInfo, dbZ != nullptr ? dbZ->primary() : nullptr, hZShapeInfo, dbZ != nullptr ? dbZ->special() : nullptr, dZShapeInfo, extraArguments); OpaqueDataBuffer::registerPrimaryUse({dbZ}, {dbX, dbY}); #endif } void execRandom2(sd::Pointer *extraPointers, int opNum, sd::Pointer state, OpaqueDataBuffer *dbX, const sd::LongType *hXShapeInfo, const sd::LongType *dXShapeInfo, OpaqueDataBuffer *dbZ, const sd::LongType *hZShapeInfo, const sd::LongType *dZShapeInfo, void *extraArguments) { #ifdef __cpp_exceptions try { OpaqueDataBuffer::preparePrimaryUse({dbZ}, {dbX}); NativeOpExecutioner::execRandom(nullptr, opNum, state, dbX != nullptr ? dbX->primary() : nullptr, hXShapeInfo, dbX != nullptr ? dbX->special() : nullptr, dXShapeInfo, dbZ != nullptr ? dbZ->primary() : nullptr, hZShapeInfo, dbZ != nullptr ? dbZ->special() : nullptr, dZShapeInfo, extraArguments); OpaqueDataBuffer::registerPrimaryUse({dbZ}, {dbX}); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else OpaqueDataBuffer::preparePrimaryUse({dbZ}, {dbX}); NativeOpExecutioner::execRandom(nullptr, opNum, state, dbX != nullptr ? dbX->primary() : nullptr, hXShapeInfo, dbX != nullptr ? dbX->special() : nullptr, dXShapeInfo, dbZ != nullptr ? dbZ->primary() : nullptr, hZShapeInfo, dbZ != nullptr ? dbZ->special() : nullptr, dZShapeInfo, extraArguments); OpaqueDataBuffer::registerPrimaryUse({dbZ}, {dbX}); #endif } sd::Pointer initRandom(sd::Pointer *extraPointers, long seed, long bufferSize, sd::Pointer ptrToBuffer) { #ifdef __cpp_exceptions try { auto generator = new sd::graph::RandomGenerator(seed, seed); return (sd::Pointer)generator; } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); THROW_EXCEPTION(e.what()); } #else auto generator = new sd::graph::RandomGenerator(seed, seed); return (sd::Pointer)generator; #endif } void refreshBuffer(sd::Pointer *extraPointers, long seed, sd::Pointer ptrRandom) { auto generator = reinterpret_cast(ptrRandom); generator->setStates(seed); } void reSeedBuffer(sd::Pointer *extraPointers, long seed, sd::Pointer ptrRandom) { auto generator = reinterpret_cast(ptrRandom); generator->setStates(seed); } void destroyRandom(sd::Pointer ptrBuffer) { auto buffer = reinterpret_cast(ptrBuffer); delete buffer; } /** * Return the length of a shape buffer * based on the pointer * @param buffer the buffer sd::Pointer to check * @return */ int lengthForShapeBufferPointer(sd::Pointer buffer) { auto shapeBuffer = reinterpret_cast(buffer); return shape::shapeInfoLength(shape::rank(shapeBuffer)); } /** * The sd::Pointer to get the address for * * @param address the address to get the pointer * @return the sd::Pointer for the given address */ sd::Pointer pointerForAddress(sd::LongType address) { return reinterpret_cast(address); } void sort(sd::Pointer *extraPointers, OpaqueNDArray x, bool descending) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execSort(x, descending); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execSort(x, descending); #endif } void sortTad(sd::Pointer *extraPointers, OpaqueNDArray x, sd::LongType *dimension, sd::LongType dimensionLength, sd::LongType *tadShapeInfo, sd::LongType *tadOffsets, bool descending) { NativeOpExecutioner::execSort(x, dimension, dimensionLength, descending); } sd::Status execCustomOp2(sd::Pointer *extraPointers, sd::LongType hash, OpaqueContext *context) { auto op = sd::ops::OpRegistrator::getInstance().getOperation(hash); // Set op name BEFORE execute() so allocations during execution are tagged // This is done unconditionally so per-op tracking works even without SD_GCC_FUNCTRACE if (op->getOpName() != nullptr) { const std::string& opName = *op->getOpName(); // Set the op context in ALL lifecycle trackers so allocations are tagged sd::array::NDArrayLifecycleTracker::setCurrentOpContext(opName); sd::array::DataBufferLifecycleTracker::setCurrentOpContext(opName); sd::graph::OpContextLifecycleTracker::setCurrentOpContext(opName); // Also update the already-tracked context with the op name sd::graph::OpContextLifecycleTracker::getInstance().updateContextOpName(context, opName); #if defined(SD_GCC_FUNCTRACE) // Also set for OpExecutionLogger when functrace is enabled sd::ops::OpExecutionLogger::setCurrentOpName(opName); #endif } auto result = op->execute(context); // Clear op context after execution sd::array::NDArrayLifecycleTracker::clearCurrentOpContext(); sd::array::DataBufferLifecycleTracker::clearCurrentOpContext(); sd::graph::OpContextLifecycleTracker::clearCurrentOpContext(); #if defined(SD_GCC_FUNCTRACE) sd::ops::OpExecutionLogger::clearCurrentOpName(); #endif checkAndCleanupCaches(); return result; } void setShapeBuffer(sd::LongType *inputShapeData,sd::DataType dt,sd::LongType *bufferToSet,char order,int elementWiseStride,bool isEmpty,bool isView) { if(inputShapeData == nullptr) THROW_EXCEPTION("setShapeBuffer: inputShapeData is null"); if(bufferToSet == nullptr) THROW_EXCEPTION("setShapeBuffer: bufferToSet is null"); sd::LongType rank = inputShapeData[0]; if(rank > SD_MAX_RANK || rank < 0) THROW_EXCEPTION("Invalid rank for shape buffer."); std::vector shape; std::vector strides; //shape, stride, data type for(sd::LongType i = 1; i < rank * 2 + 1; i++) { if(i <= rank) { shape.push_back(inputShapeData[i]); } else if(shape.size() == static_cast(rank)) { strides.push_back(inputShapeData[i]); } } bufferToSet[0] = rank; shape::setOrder(bufferToSet,order); auto len = shape::shapeInfoLength(rank); auto origShape = shape::shapeOf(inputShapeData); auto origStride = shape::stride(inputShapeData); shape::setShape(bufferToSet,origShape); shape::setStride(bufferToSet,origStride); sd::ArrayOptions::setDataType(bufferToSet,dt); if(isView) { sd::ArrayOptions::toggleIsView(bufferToSet); } if(!sd::ArrayOptions::isEmpty(inputShapeData) && isEmpty) { sd::ArrayOptions::toggleIsEmpty(bufferToSet); } if(rank == 0) { //detect when the shape buffer values are unset. auto len2 = shape::shapeInfoLength(rank); //min number of values in a shape info buffer bool allZero = true; for(int i = 0; i < len2; i++) { if(bufferToSet[i] != 0) { allZero = false; break; } } if(allZero) { THROW_EXCEPTION("Found shape buffer with all zero values. Values likely unset."); } } } //////////////////////////////////////////////////////////////////////// void setGraphContextCudaContext(sd::graph::Context *ptr, void *stream, void *reductionPointer, void *allocationPointer) {} void saveNpy(std::string fname, const OpaqueDataBuffer *data, const unsigned int *shape, const unsigned int ndims, std::string mode) { auto dtype = data->getDataBuffer()->getDataType(); BUILD_SINGLE_SELECTOR(dtype,cnpy::npy_save,(fname,data->getDataBuffer()->primary(),shape,ndims,mode),SD_COMMON_TYPES); } void sortByKey(sd::Pointer *extraPointers, OpaqueNDArray x, OpaqueNDArray y,bool descending) { #ifdef __cpp_exceptions try { auto xType = x->dataType(); auto yType = y->dataType(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortByKey(x, y, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto xType = x->dataType(); auto yType = y->dataType(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortByKey(x, y, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); #endif } void sortByValue(sd::Pointer *extraPointers, OpaqueNDArray x,OpaqueNDArray y, bool descending) { #ifdef __cpp_exceptions try { auto xType = x->dataType(); auto yType = y->dataType(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortByValue(x, y, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto xType = x->dataType(); auto yType = y->dataType(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortByValue(x, y, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); #endif } void sortTadByKey(sd::Pointer *extraPointers, OpaqueNDArray x, OpaqueNDArray y, OpaqueNDArray dimension, bool descending) { #ifdef __cpp_exceptions try { auto xType = x->dataType(); auto yType = y->dataType(); auto dimensionLength = dimension->lengthOf(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortTadByValue(x, y, dimension, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto xType = x->dataType(); auto yType = y->dataType(); auto dimensionLength = dimension->lengthOf(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortTadByValue(x, y, dimension, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); #endif } void sortTadByValue(sd::Pointer *extraPointers, OpaqueNDArray x, OpaqueNDArray y,OpaqueNDArray dimension, bool descending) { #ifdef __cpp_exceptions try { auto xType = x->dataType(); auto yType = y->dataType(); auto dimensionLength = dimension->lengthOf(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortTadByValue(x, y, dimension, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto xType = x->dataType(); auto yType = y->dataType(); auto dimensionLength = dimension->lengthOf(); BUILD_DOUBLE_SELECTOR(xType, yType, sd::DoubleMethods, ::sortTadByValue(x, y, dimension, descending), SD_NUMERIC_TYPES, SD_NUMERIC_TYPES); #endif } void execIndexReduceScalar(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,void *extraParams, OpaqueNDArray z) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execIndexReduceScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo()); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execIndexReduceScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo()); #endif } void execIndexReduce(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams, OpaqueNDArray z, OpaqueNDArray dimension ) { #ifdef __cpp_exceptions try { auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto hTADShapeInfo = tadPack->primaryShapeInfo(); auto hTADOffsets = tadPack->primaryOffsets(); NativeOpExecutioner::execIndexReduce(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), hTADShapeInfo, hTADOffsets); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto hTADShapeInfo = tadPack->primaryShapeInfo(); auto hTADOffsets = tadPack->primaryOffsets(); NativeOpExecutioner::execIndexReduce(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), hTADShapeInfo, hTADOffsets); #endif } void execBroadcast(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray y, OpaqueNDArray z,void *extraInfo, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { auto tadPackX = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto tadPackZ = sd::ConstantTadHelper::getInstance().tadForDimensions(z->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); #if defined(PRINT_INDICES) printf("broadcast exec tad full x\n"); shape::printShapeInfo(x->shapeInfo()); printf("broadcast exec tad full y\n"); shape::printShapeInfo(y->shapeInfo()); printf("broadcast exec tad full z\n"); shape::printShapeInfo(z->shapeInfo()); #endif auto hTADShapeInfo = tadPackX->primaryShapeInfo(); auto hTADOffsets = tadPackX->primaryOffsets(); auto hTADShapeInfoZ = tadPackZ->primaryShapeInfo(); auto hTADOffsetsZ = tadPackZ->primaryOffsets(); NativeOpExecutioner::execBroadcast(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), hTADShapeInfo, hTADOffsets, hTADShapeInfoZ, hTADOffsetsZ); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto tadPackX = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto tadPackZ = sd::ConstantTadHelper::getInstance().tadForDimensions(z->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); #if defined(PRINT_INDICES) printf("broadcast exec tad full x\n"); shape::printShapeInfo(x->shapeInfo()); printf("broadcast exec tad full y\n"); shape::printShapeInfo(y->shapeInfo()); printf("broadcast exec tad full z\n"); shape::printShapeInfo(z->shapeInfo()); #endif auto hTADShapeInfo = tadPackX->primaryShapeInfo(); auto hTADOffsets = tadPackX->primaryOffsets(); auto hTADShapeInfoZ = tadPackZ->primaryShapeInfo(); auto hTADOffsetsZ = tadPackZ->primaryOffsets(); NativeOpExecutioner::execBroadcast(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), hTADShapeInfo, hTADOffsets, hTADShapeInfoZ, hTADOffsetsZ); #endif } void execPairwiseTransform(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray y, OpaqueNDArray z, void *extraParams) { #ifdef __cpp_exceptions try { /** * TODO: look in to offsets here as left over change from ndarrays being available? */ NativeOpExecutioner::execPairwiseTransform(nullptr, opNum, x->bufferWithOffset(x->offset()), x->shapeInfo(), x->specialBufferWithOffset(x->offset()), x->specialShapeInfo(), y->bufferWithOffset(y->offset()), y->shapeInfo(), y->specialBufferWithOffset(y->offset()), y->specialShapeInfo(), z->bufferWithOffset(z->offset()), z->shapeInfo(), const_cast(z->specialBufferWithOffset(z->offset())), z->specialShapeInfo(), extraParams); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else /** * TODO: look in to offsets here as left over change from ndarrays being available? */ NativeOpExecutioner::execPairwiseTransform(nullptr, opNum, x->bufferWithOffset(x->offset()), x->shapeInfo(), x->specialBufferWithOffset(x->offset()), x->specialShapeInfo(), y->bufferWithOffset(y->offset()), y->shapeInfo(), y->specialBufferWithOffset(y->offset()), y->specialShapeInfo(), z->bufferWithOffset(z->offset()), z->shapeInfo(), const_cast(z->specialBufferWithOffset(z->offset())), z->specialShapeInfo(), extraParams); #endif } void execReduceFloat(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams, OpaqueNDArray z) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat: null shapeInfo in input arrays"); return; } NativeOpExecutioner::execReduceFloatScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo()); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat: null shapeInfo in input arrays"); return; } NativeOpExecutioner::execReduceFloatScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo()); checkAndCleanupCaches(); #endif } void execReduceSame(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams,OpaqueNDArray z) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame: null shapeInfo in input arrays"); return; } NativeOpExecutioner::execReduceSameScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo()); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame: null shapeInfo in input arrays"); return; } NativeOpExecutioner::execReduceSameScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo()); checkAndCleanupCaches(); #endif } void execReduceBool(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams, OpaqueNDArray z, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool: null shapeInfo in input arrays"); return; } // Removed unused TAD pack creation that was causing cache bloat and memory leaks // The NativeOpExecutioner::execReduceBool handles TAD operations internally NativeOpExecutioner::execReduceBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT (), dimension->lengthOf()); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool: null shapeInfo in input arrays"); return; } // Removed unused TAD pack creation that was causing cache bloat and memory leaks // The NativeOpExecutioner::execReduceBool handles TAD operations internally NativeOpExecutioner::execReduceBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT (), dimension->lengthOf()); checkAndCleanupCaches(); #endif } void execReduceLong(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams, OpaqueNDArray z, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong: null shapeInfo in input arrays"); return; } // Removed unused TAD pack creation that was causing cache bloat and memory leaks // The NativeOpExecutioner::execReduceLong handles TAD operations internally NativeOpExecutioner::execReduceLong(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT (), dimension->lengthOf()); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong: null shapeInfo in input arrays"); return; } // Removed unused TAD pack creation that was causing cache bloat and memory leaks // The NativeOpExecutioner::execReduceLong handles TAD operations internally NativeOpExecutioner::execReduceLong(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT (), dimension->lengthOf()); checkAndCleanupCaches(); #endif } void execReduceFloat2(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,void *extraParams, OpaqueNDArray z, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat2: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat2: null shapeInfo in input arrays"); return; } std::vector dimensions(dimension->lengthOf()); for(sd::LongType i = 0; i < dimension->lengthOf(); i++) { sd::LongType curr = dimension->e(i); if(curr < 0) { curr += x->rankOf(); } dimensions[i] = curr; } const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); if (shape::rank(x->shapeInfo()) - dimension->lengthOf() != shape::rank(z->shapeInfo()) && z->lengthOf() != 1) { auto zPack = sd::ConstantShapeHelper::getInstance().createShapeInfoWithNoUnitiesForReduce(z->shapeInfo(), &dimensions); zShapeInfoH = reinterpret_cast(zPack->primary()); zShapeInfoD = reinterpret_cast(zPack->special()); } std::vector *dims = (z->lengthOf() != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(x->shapeInfo()), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceFloat(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), zShapeInfoH, z->specialBuffer(), zShapeInfoD, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat2: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceFloat2: null shapeInfo in input arrays"); return; } std::vector dimensions(dimension->lengthOf()); for(sd::LongType i = 0; i < dimension->lengthOf(); i++) { sd::LongType curr = dimension->e(i); if(curr < 0) { curr += x->rankOf(); } dimensions[i] = curr; } const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); if (shape::rank(x->shapeInfo()) - dimension->lengthOf() != shape::rank(z->shapeInfo()) && z->lengthOf() != 1) { auto zPack = sd::ConstantShapeHelper::getInstance().createShapeInfoWithNoUnitiesForReduce(z->shapeInfo(), &dimensions); zShapeInfoH = reinterpret_cast(zPack->primary()); zShapeInfoD = reinterpret_cast(zPack->special()); } std::vector *dims = (z->lengthOf() != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(x->shapeInfo()), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceFloat(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), zShapeInfoH, z->specialBuffer(), zShapeInfoD, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); #endif } void execReduceBool2(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams, OpaqueNDArray z, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool2: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool2: null shapeInfo in input arrays"); return; } std::vector dimensions(dimension->lengthOf()); for(sd::LongType i = 0; i < dimension->lengthOf(); i++) { sd::LongType curr = dimension->e(i); if(curr < 0) { curr += x->rankOf(); } dimensions[i] = curr; } const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); if (shape::rank(x->shapeInfo()) - dimension->lengthOf() != shape::rank(z->shapeInfo())) { auto zPack = sd::ConstantShapeHelper::getInstance().createShapeInfoWithNoUnitiesForReduce(z->shapeInfo(), &dimensions); zShapeInfoH = reinterpret_cast(zPack->primary()); zShapeInfoD = reinterpret_cast(zPack->special()); } std::vector *dims = (z->lengthOf() != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(x->shapeInfo()), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), zShapeInfoH, z->specialBuffer(), zShapeInfoD, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool2: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceBool2: null shapeInfo in input arrays"); return; } std::vector dimensions(dimension->lengthOf()); for(sd::LongType i = 0; i < dimension->lengthOf(); i++) { sd::LongType curr = dimension->e(i); if(curr < 0) { curr += x->rankOf(); } dimensions[i] = curr; } const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); if (shape::rank(x->shapeInfo()) - dimension->lengthOf() != shape::rank(z->shapeInfo())) { auto zPack = sd::ConstantShapeHelper::getInstance().createShapeInfoWithNoUnitiesForReduce(z->shapeInfo(), &dimensions); zShapeInfoH = reinterpret_cast(zPack->primary()); zShapeInfoD = reinterpret_cast(zPack->special()); } std::vector *dims = (z->lengthOf() != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(x->shapeInfo()), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), zShapeInfoH, z->specialBuffer(), zShapeInfoD, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); #endif } void execReduceSame2(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,void *extraParams, OpaqueNDArray z, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame2: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame2: null shapeInfo in input arrays"); return; } std::vector dimensions(dimension->lengthOf()); for(sd::LongType i = 0; i < dimension->lengthOf(); i++) { sd::LongType curr = dimension->e(i); if(curr < 0) { curr += x->rankOf(); } dimensions[i] = curr; } const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); if (shape::rank(x->shapeInfo()) - dimension->lengthOf() != shape::rank(z->shapeInfo()) && z->lengthOf() != 1) { auto zPack = sd::ConstantShapeHelper::getInstance().createShapeInfoWithNoUnitiesForReduce(z->shapeInfo(), &dimensions); zShapeInfoH = reinterpret_cast(zPack->primary()); zShapeInfoD = reinterpret_cast(zPack->special()); } std::vector *dims = (z->lengthOf() != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(x->shapeInfo()), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceSame(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), zShapeInfoH, z->specialBuffer(), zShapeInfoD, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr || z == nullptr || dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame2: null pointer in input parameters"); return; } if (x->shapeInfo() == nullptr || z->shapeInfo() == nullptr || dimension->shapeInfo() == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceSame2: null shapeInfo in input arrays"); return; } std::vector dimensions(dimension->lengthOf()); for(sd::LongType i = 0; i < dimension->lengthOf(); i++) { sd::LongType curr = dimension->e(i); if(curr < 0) { curr += x->rankOf(); } dimensions[i] = curr; } const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); if (shape::rank(x->shapeInfo()) - dimension->lengthOf() != shape::rank(z->shapeInfo()) && z->lengthOf() != 1) { auto zPack = sd::ConstantShapeHelper::getInstance().createShapeInfoWithNoUnitiesForReduce(z->shapeInfo(), &dimensions); zShapeInfoH = reinterpret_cast(zPack->primary()); zShapeInfoD = reinterpret_cast(zPack->special()); } std::vector *dims = (z->lengthOf() != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(x->shapeInfo()), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceSame(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), zShapeInfoH, z->specialBuffer(), zShapeInfoD, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); #endif } void execReduceLong2(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams, OpaqueNDArray z, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { // Validate input pointers to prevent segfault if (x == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: input array x is null"); return; } if (z == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: output array z is null"); return; } if (dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: dimension array is null"); return; } // If we validate first (call shapeInfo()), then cache later (call shapeInfo() again), // the pointer could become invalid between the two calls, causing SIGSEGV. // By caching once and validating the cached value, we ensure consistency. const sd::LongType *xShapeInfoH = x->shapeInfo(); const sd::LongType *xShapeInfoD = x->specialShapeInfo(); void *xBuffer = x->buffer(); void *xSpecialBuffer = x->specialBuffer(); void *zBuffer = z->buffer(); const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); const sd::LongType zLength = z->lengthOf(); if (xShapeInfoH == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: input array x has null shapeInfo"); return; } if (zShapeInfoH == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: output array z has null shapeInfo"); return; } void *dimensionBuffer = dimension->buffer(); sd::DataBuffer *dimensionDb = dimension->getDataBuffer(); if (dimensionBuffer == nullptr || dimensionDb == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: dimension array has null buffer"); return; } const sd::LongType xRank = shape::rank(xShapeInfoH); const sd::DataType dimType = dimension->dataType(); if (dimType != sd::DataType::INT32 && dimType != sd::DataType::INT64) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); std::string err = "execReduceLong2: unsupported dimension buffer data type: "; err += sd::DataTypeUtils::asString(dimType); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(err.c_str()); return; } const sd::LongType dimensionLength = static_cast(dimensionDb->getLenInBytes() / sd::DataTypeUtils::sizeOf(dimType)); // Extract dimension values directly from the raw buffer. Do not rely on dimension->shapeInfo() // because some callers mutate or free the dimension shape buffer once the NDArray is created. std::vector dimensions(dimensionLength); if (dimensionLength > 0) { if (dimType == sd::DataType::INT32) { auto dimensionData = reinterpret_cast(dimensionBuffer); for (sd::LongType i = 0; i < dimensionLength; i++) { sd::LongType curr = static_cast(dimensionData[i]); if (curr < 0) { curr += xRank; } dimensions[i] = curr; } } else { auto dimensionData = reinterpret_cast(dimensionBuffer); for (sd::LongType i = 0; i < dimensionLength; i++) { sd::LongType curr = dimensionData[i]; if (curr < 0) { curr += xRank; } dimensions[i] = curr; } } } // Validate output shape matches expected dimensions after reduction // If ranks don't match, this indicates a shape mismatch from the calling layer // DO NOT attempt to reshape - the buffer and shape must match if (shape::rank(xShapeInfoH) - dimensionLength != shape::rank(zShapeInfoH) && zLength != 1) { std::string errorMsg = "execReduceLong2: Output shape rank mismatch. "; errorMsg += "Input rank: " + std::to_string(shape::rank(xShapeInfoH)); errorMsg += ", reduction dimensions: " + std::to_string(dimensionLength); errorMsg += ", expected output rank: " + std::to_string(shape::rank(xShapeInfoH) - dimensionLength); errorMsg += ", but got output rank: " + std::to_string(shape::rank(zShapeInfoH)); THROW_EXCEPTION(errorMsg.c_str()); } std::vector *dims = (zLength != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(xShapeInfoH), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceLong(nullptr, opNum, xBuffer, xShapeInfoH, xSpecialBuffer, xShapeInfoD, extraParams, zBuffer, zShapeInfoH, nullptr, nullptr, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else // Validate input pointers to prevent segfault if (x == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: input array x is null"); return; } if (z == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: output array z is null"); return; } if (dimension == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: dimension array is null"); return; } // If we validate first (call shapeInfo()), then cache later (call shapeInfo() again), // the pointer could become invalid between the two calls, causing SIGSEGV. // By caching once and validating the cached value, we ensure consistency. const sd::LongType *xShapeInfoH = x->shapeInfo(); const sd::LongType *xShapeInfoD = x->specialShapeInfo(); void *xBuffer = x->buffer(); void *xSpecialBuffer = x->specialBuffer(); void *zBuffer = z->buffer(); const sd::LongType *zShapeInfoH = z->shapeInfo(); const sd::LongType *zShapeInfoD = z->specialShapeInfo(); const sd::LongType zLength = z->lengthOf(); if (xShapeInfoH == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: input array x has null shapeInfo"); return; } if (zShapeInfoH == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: output array z has null shapeInfo"); return; } void *dimensionBuffer = dimension->buffer(); sd::DataBuffer *dimensionDb = dimension->getDataBuffer(); if (dimensionBuffer == nullptr || dimensionDb == nullptr) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage("execReduceLong2: dimension array has null buffer"); return; } const sd::LongType xRank = shape::rank(xShapeInfoH); const sd::DataType dimType = dimension->dataType(); if (dimType != sd::DataType::INT32 && dimType != sd::DataType::INT64) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); std::string err = "execReduceLong2: unsupported dimension buffer data type: "; err += sd::DataTypeUtils::asString(dimType); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(err.c_str()); return; } const sd::LongType dimensionLength = static_cast(dimensionDb->getLenInBytes() / sd::DataTypeUtils::sizeOf(dimType)); // Extract dimension values directly from the raw buffer. Do not rely on dimension->shapeInfo() // because some callers mutate or free the dimension shape buffer once the NDArray is created. std::vector dimensions(dimensionLength); if (dimensionLength > 0) { if (dimType == sd::DataType::INT32) { auto dimensionData = reinterpret_cast(dimensionBuffer); for (sd::LongType i = 0; i < dimensionLength; i++) { sd::LongType curr = static_cast(dimensionData[i]); if (curr < 0) { curr += xRank; } dimensions[i] = curr; } } else { auto dimensionData = reinterpret_cast(dimensionBuffer); for (sd::LongType i = 0; i < dimensionLength; i++) { sd::LongType curr = dimensionData[i]; if (curr < 0) { curr += xRank; } dimensions[i] = curr; } } } // Validate output shape matches expected dimensions after reduction // If ranks don't match, this indicates a shape mismatch from the calling layer // DO NOT attempt to reshape - the buffer and shape must match if (shape::rank(xShapeInfoH) - dimensionLength != shape::rank(zShapeInfoH) && zLength != 1) { std::string errorMsg = "execReduceLong2: Output shape rank mismatch. "; errorMsg += "Input rank: " + std::to_string(shape::rank(xShapeInfoH)); errorMsg += ", reduction dimensions: " + std::to_string(dimensionLength); errorMsg += ", expected output rank: " + std::to_string(shape::rank(xShapeInfoH) - dimensionLength); errorMsg += ", but got output rank: " + std::to_string(shape::rank(zShapeInfoH)); THROW_EXCEPTION(errorMsg.c_str()); } std::vector *dims = (zLength != 1) ? sd::ShapeUtils::evalDimsForReduceOp(shape::rank(xShapeInfoH), &dimensions) : new std::vector(); NativeOpExecutioner::execReduceLong(nullptr, opNum, xBuffer, xShapeInfoH, xSpecialBuffer, xShapeInfoD, extraParams, zBuffer, zShapeInfoH, nullptr, nullptr, dims->data(), dims->size()); delete dims; checkAndCleanupCaches(); #endif } void execReduce3Tad(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams,OpaqueNDArray y, OpaqueNDArray z, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto hTADShapeInfo = tadPack->primaryShapeInfo(); auto hTADOffsets = tadPack->primaryOffsets(); NativeOpExecutioner::execReduce3TAD(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), hTADShapeInfo, hTADOffsets, nullptr, nullptr); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); auto hTADShapeInfo = tadPack->primaryShapeInfo(); auto hTADOffsets = tadPack->primaryOffsets(); NativeOpExecutioner::execReduce3TAD(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), hTADShapeInfo, hTADOffsets, nullptr, nullptr); checkAndCleanupCaches(); #endif } void execScalar(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray z, OpaqueNDArray scalar, void *extraParams) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), extraParams); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), extraParams); checkAndCleanupCaches(); #endif } void execScalarBool(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray z, OpaqueNDArray scalar, void *extraParams) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execScalarBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), extraParams); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execScalarBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), extraParams); checkAndCleanupCaches(); #endif } void execSummaryStatsScalar(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams, OpaqueNDArray z, bool biasCorrected) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execSummaryStatsScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), biasCorrected); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execSummaryStatsScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), biasCorrected); #endif } void execSummaryStats(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray z, void *extraParams, bool biasCorrected) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execSummaryStats(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), biasCorrected); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execSummaryStats(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), biasCorrected); #endif } void execSummaryStatsTad(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams,OpaqueNDArray z, OpaqueNDArray dimension, bool biasCorrected) { #ifdef __cpp_exceptions try { auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->shapeOf(), dimension->lengthOf()); NativeOpExecutioner::execSummaryStats(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets(), biasCorrected); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->shapeOf(), dimension->lengthOf()); NativeOpExecutioner::execSummaryStats(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets(), biasCorrected); #endif } void execTransformFloat(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, void *extraParams,OpaqueNDArray z) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execTransformFloat(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execTransformFloat(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); checkAndCleanupCaches(); #endif } void execTransformSame(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,void *extraParams, OpaqueNDArray z) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execTransformSame(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams, nullptr, nullptr); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execTransformSame(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams, nullptr, nullptr); checkAndCleanupCaches(); #endif } void execTransformBool(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,void *extraParams, OpaqueNDArray z) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execTransformBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execTransformBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); checkAndCleanupCaches(); #endif } void execTransformAny(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,void *extraParams, OpaqueNDArray z) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execTransformAny(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams, false); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execTransformAny(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams, false); checkAndCleanupCaches(); #endif } void execTransformStrict(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x,void *extraParams, OpaqueNDArray z) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execTransformStrict(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); checkAndCleanupCaches(); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execTransformStrict(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); checkAndCleanupCaches(); #endif } void execReduce3All(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray y, OpaqueNDArray z, OpaqueNDArray dimension, void *extraParams) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execReduce3All(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), nullptr, nullptr, nullptr, nullptr); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execReduce3All(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), nullptr, nullptr, nullptr, nullptr); #endif } void execRandom(sd::Pointer *extraPointers, int opNum, sd::Pointer state, OpaqueNDArray z, void *extraArguments) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execRandom(nullptr, opNum, state, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraArguments); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execRandom(nullptr, opNum, state, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraArguments); #endif } void execRandom3(sd::Pointer *extraPointers, int opNum, sd::Pointer state, OpaqueNDArray x, OpaqueNDArray y, OpaqueNDArray z, void *extraArguments) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execRandom(nullptr, opNum, state, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraArguments); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execRandom(nullptr, opNum, state, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraArguments); #endif } void execScalarTad(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray z, OpaqueNDArray scalar,void *extraParams, OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); NativeOpExecutioner::execScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets()); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); NativeOpExecutioner::execScalar(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets()); #endif } void execScalarBoolTad(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray z, OpaqueNDArray scalar, void *extraParams,OpaqueNDArray dimension) { #ifdef __cpp_exceptions try { auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); NativeOpExecutioner::execScalarBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets()); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else auto tadPack = sd::ConstantTadHelper::getInstance().tadForDimensions(x->shapeInfo(), dimension->bufferAsT(), dimension->lengthOf()); NativeOpExecutioner::execScalarBool(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), extraParams, z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), scalar->buffer(), scalar->shapeInfo(), scalar->specialBuffer(), scalar->specialShapeInfo(), dimension->bufferAsT(), dimension->lengthOf(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets(), tadPack->primaryShapeInfo(), tadPack->primaryOffsets()); #endif } void execPairwiseTransformBool(sd::Pointer *extraPointers, int opNum, OpaqueNDArray x, OpaqueNDArray y, void *extraParams,OpaqueNDArray z) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execPairwiseBoolTransform(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execPairwiseBoolTransform(nullptr, opNum, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), y->buffer(), y->shapeInfo(), y->specialBuffer(), y->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraParams); #endif } void execRandom2(sd::Pointer *extraPointers, int opNum, sd::Pointer state, OpaqueNDArray x, OpaqueNDArray z, void *extraArguments) { #ifdef __cpp_exceptions try { NativeOpExecutioner::execRandom(nullptr, opNum, state, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraArguments); } catch (std::exception &e) { sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1); sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what()); } #else NativeOpExecutioner::execRandom(nullptr, opNum, state, x->buffer(), x->shapeInfo(), x->specialBuffer(), x->specialShapeInfo(), z->buffer(), z->shapeInfo(), z->specialBuffer(), z->specialShapeInfo(), extraArguments); #endif } int binaryLevel() { #ifdef CPU_FEATURES #if defined(F_X64) return 1; #elif defined(F_AVX2) return 2; #elif defined(F_AVX512) return 3; #else return 0; #endif #else return 0; #endif } int optimalLevel() { #ifdef CPU_FEATURES auto features = cpu_features::GetX86Info().features; if (features.avx && features.avx2 && features.avx512f && features.avx512vl && features.avx512bw && features.avx512dq && features.avx512cd) return 3; else if (features.avx && features.avx2) return 2; else return 1; #else return 0; #endif } bool isMinimalRequirementsMet() { #ifdef CPU_FEATURES auto features = cpu_features::GetX86Info().features; #if defined(F_X64) return true; #elif defined(F_AVX2) return features.avx && features.avx2; #elif defined(F_AVX512) // we're optimizing for skylake-avx512 features, so we'll check those out return features.avx && features.avx2 && features.avx512f && features.avx512vl && features.avx512bw && features.avx512dq && features.avx512cd; #else return true; #endif #else return true; #endif } bool isOptimalRequirementsMet() { #ifdef CPU_FEATURES auto b = ::binaryLevel(); auto o = ::optimalLevel(); if (b == o) return true; else return false; #else return true; #endif } template void _printHostBuffer(OpaqueDataBuffer *buffer, sd::LongType offset) { auto xType = buffer->dataBuffer()->getDataType(); sd::LongType len = buffer->dataBuffer()->getNumElements(); auto buff = buffer->dataBuffer()->template primaryAsT(); sd_printf("Data type %s: ", sd::DataTypeUtils::asString(xType).c_str()); sd_printf("Host buffer: ",0); for(int i = offset; i < len; i++) { sd_printf("%f ",(double) buff[i]); } sd_printf("\n",0); } void printDeviceBuffer(OpaqueDataBuffer *buffer) { printDeviceBuffer(buffer, 0); } void printDeviceBuffer(OpaqueDataBuffer *buffer, sd::LongType offset) { if(buffer->special() != nullptr) { sd_printf("Device sd::Pointer address: %d\n", buffer->special()); } else { sd_printf("Device sd::Pointer address: none\n",0); } if(buffer->primary() != nullptr) { sd_printf("Host sd::Pointer address: %d\n", buffer->primary()); } else { sd_printf("Host sd::Pointer address: none\n",0); } auto xType = buffer->dataBuffer()->getDataType(); BUILD_SINGLE_SELECTOR(xType, _printHostBuffer,(buffer,offset),SD_COMMON_TYPES); } BUILD_SINGLE_TEMPLATE( void pullRowsGeneric, (OpaqueNDArray, OpaqueNDArray, const int, OpaqueNDArray, sd::LongType), SD_COMMON_TYPES); BUILD_SINGLE_TEMPLATE( void tearGeneric, (void *, sd::LongType const *, sd::Pointer *, sd::LongType const *, sd::LongType const *,sd::LongType const *), SD_COMMON_TYPES); BUILD_SINGLE_TEMPLATE( void shuffleGeneric, (OpaqueNDArrayArr, OpaqueNDArrayArr, int, int *,sd::LongType *, sd::LongType), SD_COMMON_TYPES);