Files
2026-07-13 12:47:05 +08:00

2165 lines
70 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
******************************************************************************/
#include <graph/GraphExecutioner.h>
#include <graph/GraphHolder.h>
#include <helpers/ConstantTadHelper.h>
#include <legacy/NativeOps.h>
#include <ops/declarable/OpRegistrator.h>
#include "execution/Threads.h"
#include "helpers/OpTracker.h"
#include <exceptions/allocation_exception.h>
#include <fcntl.h>
#include <graph/GraphExecutioner.h>
#include <helpers/BlasHelper.h>
#include <helpers/helper_ptrmap.h>
#include <helpers/logger.h>
#include <legacy/NativeOpExecutioner.h>
#include <legacy/NativeOps.h>
#include <loops/type_conversions.h>
#include <math/templatemath.h>
#include <ops/declarable/helpers/transforms.h>
#include <stdio.h>
#include <stdlib.h>
#include <types/float8.h>
#include <types/types.h>
#ifndef _WIN32
#include <sys/mman.h>
#include <unistd.h>
#else
#include <helpers/mman.h>
#include <io.h>
#endif
#include <errno.h>
#include <ops/declarable/CustomOperations.h>
#include <sys/types.h>
bool experimentalSupport = false;
#include <execution/Threads.h>
#include <graph/Context.h>
#include <graph/ResultWrapper.h>
#include <helpers/ConstantTadHelper.h>
#include <helpers/DebugHelper.h>
#include <ops/declarable/OpRegistrator.h>
#include <ops/specials.h>
#include <system/Environment.h>
#ifdef CPU_FEATURES
#include <cpuinfo_x86.h>
#endif
#include <array/DataType.h>
#include <array/DataTypeUtils.h>
/*
* TypeDef:
* void convertTypes(Pointer *extras, DataType srcType, Pointer hX, long N, DataType dstType, Pointer hZ);
*/
void convertTypes(sd::Pointer *extras, int srcTypeInt, sd::Pointer hX, sd::LongType N, int destType, sd::Pointer hZ) {
sd::DataType srcType = sd::DataTypeUtils::fromInt(srcTypeInt);
sd::DataType dstType = sd::DataTypeUtils::fromInt(destType);
auto hx = reinterpret_cast<void *>(hX);
auto hz = reinterpret_cast<void *>(hZ);
#ifdef HAS_FLOAT8
if (srcType == sd::DataType::FLOAT8) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT8, float8, DOUBLE, double);
} else
#endif
{
sd_debug("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_FLOAT8
#ifdef HAS_INT8
if (srcType == sd::DataType::INT8) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT8, int8_t, DOUBLE, double);
} else
#endif
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_INT8
#ifdef HAS_UINT8
if (srcType == sd::DataType::UINT8) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT8, uint8_t, DOUBLE, double);
} else
#endif
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_UINT8
#ifdef HAS_FLOAT16
if (srcType == sd::DataType::HALF) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), HALF, float16, DOUBLE, double);
} else
#endif
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_FLOAT16
#ifdef HAS_INT16
if (srcType == sd::DataType::INT16) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), INT16, int16_t, DOUBLE, double);
} else
#endif
{
printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_INT16
#ifdef HAS_FLOAT32
if (srcType == sd::DataType::FLOAT32) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
// No conversion needed - same type
if (hx != hz) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, FLOAT32, float);
}
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), FLOAT32, float, DOUBLE, double);
} else
#endif
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_FLOAT32
#ifdef HAS_DOUBLE
if (srcType == sd::DataType::DOUBLE) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
// No conversion needed - same type
if (hx != hz) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), DOUBLE, double, DOUBLE, double);
}
} else
#endif
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_DOUBLE
#ifdef HAS_BFLOAT16
if (srcType == sd::DataType::BFLOAT16) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, UINT16, uint16_t);
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, DOUBLE, double);
} else
#endif
#ifdef HAS_BFLOAT16
if (dstType == sd::DataType::BFLOAT16) {
// No conversion needed - same type
if (hx != hz) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), BFLOAT16, bfloat16, BFLOAT16, bfloat16);
}
} else
#endif
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_BFLOAT16
#ifdef HAS_UINT16
if (srcType == sd::DataType::UINT16) {
#ifdef HAS_FLOAT8
if (dstType == sd::DataType::FLOAT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, FLOAT8, float8);
} else
#endif
#ifdef HAS_INT8
if (dstType == sd::DataType::INT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, INT8, int8_t);
} else
#endif
#ifdef HAS_UINT8
if (dstType == sd::DataType::UINT8) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, UINT8, uint8_t);
} else
#endif
#ifdef HAS_FLOAT16
if (dstType == sd::DataType::HALF) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, HALF, float16);
} else
#endif
#ifdef HAS_INT16
if (dstType == sd::DataType::INT16) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, INT16, int16_t);
} else
#endif
#ifdef HAS_UINT16
if (dstType == sd::DataType::UINT16) {
// No conversion needed - same type
if (hx != hz) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, UINT16, uint16_t);
}
} else
#endif
#ifdef HAS_FLOAT32
if (dstType == sd::DataType::FLOAT32) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, FLOAT32, float);
} else
#endif
#ifdef HAS_DOUBLE
if (dstType == sd::DataType::DOUBLE) {
_CALL_DOUBLE2(sd::TypeCast::convertGeneric, (nullptr, hx, N, hz), UINT16, uint16_t, DOUBLE, double);
} else
#endif
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
} else
#endif // HAS_UINT16
{
sd_printf("Unsupported types conversion: [%s] -> [%s]\n",
sd::DataTypeUtils::asString(srcType).c_str(),
sd::DataTypeUtils::asString(dstType).c_str());
}
}
static long lengthInBytes(OpaqueDataBuffer *buffer) {
return buffer->dataBuffer()->getLenInBytes();
}
template <typename T>
static sd::Pointer _numpyHeaderForNd4j(sd::Pointer data, const sd::Pointer shapeBuffer, sd::LongType wordSize,
sd::LongType* headerSize) {
sd::LongType const* shapeBufferCast = reinterpret_cast<const sd::LongType*>(shapeBuffer);
int rank = shape::rank(shapeBufferCast);
const sd::LongType* shape = shape::shapeOf(shapeBufferCast);
unsigned int* npShape = new unsigned int[rank];
for (int i = 0; i < rank; i++) {
npShape[i] = shape[i];
}
sd::LongType length = shape::prodLong(shape, rank);
auto npHeader = cnpy::createNpyHeader<T>(npShape, rank, wordSize);
char* ret = new char[npHeader.size() + 1];
int count = 0;
for (size_t i = 0; i < npHeader.size(); i++) {
ret[count] = npHeader[i];
count++;
}
ret[count] = '\0';
count++;
*headerSize = count;
return reinterpret_cast<sd::Pointer>(ret);
}
sd::Pointer numpyHeaderForNd4j(sd::Pointer data, sd::Pointer shapeBuffer, sd::LongType wordSize,
sd::LongType* headerSize) {
auto shapeBufferCast = reinterpret_cast<sd::LongType*>(shapeBuffer);
auto type = sd::ArrayOptions::dataType(shapeBufferCast);
BUILD_SINGLE_SELECTOR(type, return _numpyHeaderForNd4j, (data, shapeBuffer, wordSize, headerSize), SD_COMMON_TYPES);
return nullptr;
}
/**
* Load numpy from a header
* based on the cnpy parse from header method.
* @param data the header data to parse
* @return a pointer to a numpy cnpy:NpyArray struct
*/
sd::Pointer loadNpyFromHeader(sd::Pointer data) {
char* header = reinterpret_cast<char*>(data);
cnpy::NpyArray arr = cnpy::loadNpyFromHeader(header);
cnpy::NpyArray* ret = new cnpy::NpyArray();
ret->data = arr.data;
ret->wordSize = arr.wordSize;
ret->shape = arr.shape;
return reinterpret_cast<sd::Pointer>(ret);
}
/**
* Create a numpy array from an nd4j
* array
* @param data a pointer to the data
* @param shapeBuffer the shapebuffer for the nd4j array
* @param wordSize the word size (4 for float, 8 for doubles)
* @return a pointer to a numpy array
*/
template <typename T>
sd::Pointer _numpyFromNd4j(sd::Pointer data, sd::Pointer shapeBuffer, sd::LongType wordSize) {
sd::LongType* shapeBufferCast = reinterpret_cast<sd::LongType*>(shapeBuffer);
int rank = shape::rank(shapeBufferCast);
sd::LongType* shape = shape::shapeOf(shapeBufferCast);
unsigned int* npShape = new unsigned int[rank];
for (int i = 0; i < rank; i++) {
npShape[i] = shape[i];
}
sd::LongType length = shape::prodLong(shape, rank);
auto npHeader = cnpy::createNpyHeader<T>( npShape, rank, wordSize);
char* dataChar = reinterpret_cast<char*>(data);
char* npHeaderData = npHeader.data();
char* ret = new char[(wordSize * length) + npHeader.size()];
char* cursorStart = ret + npHeader.size();
std::memcpy(ret, npHeaderData,
npHeader.size());
std::memcpy(cursorStart, dataChar,length * wordSize);
sd::Pointer rettPointer = reinterpret_cast<sd::Pointer>(ret);
return rettPointer;
}
template<typename T>
long _numpyHeaderLength(OpaqueDataBuffer *opaqueDataBuffer,sd::Pointer shapeBuffer) {
sd::LongType wordSize = opaqueDataBuffer->dataBuffer()->getLenInBytes() / opaqueDataBuffer->dataBuffer()->getNumElements();
sd::LongType* shapeBufferCast = reinterpret_cast<sd::LongType*>(shapeBuffer);
int rank = shape::rank(shapeBufferCast);
sd::LongType* shape = shape::shapeOf(shapeBufferCast);
unsigned int* npShape = new unsigned int[rank];
for (int i = 0; i < rank; i++) {
npShape[i] = shape[i];
}
sd::LongType length = shape::prodLong(shape, rank);
auto npHeader = cnpy::createNpyHeader<T>(npShape, rank, wordSize);
long ret = npHeader.size();
return ret;
}
template<typename T>
long _numpyHeaderLengthWordSize(sd::Pointer shapeBuffer,long wordSize) {
sd::LongType* shapeBufferCast = reinterpret_cast<sd::LongType*>(shapeBuffer);
int rank = shape::rank(shapeBufferCast);
sd::LongType* shape = shape::shapeOf(shapeBufferCast);
unsigned int* npShape = new unsigned int[rank];
for (int i = 0; i < rank; i++) {
npShape[i] = shape[i];
}
sd::LongType length = shape::prodLong(shape, rank);
auto npHeader = cnpy::createNpyHeader<T>(npShape, rank, wordSize);
long ret = npHeader.size();
return ret;
}
long numpyHeaderLengthWordSize(sd::Pointer shapeBuffer,long wordSize) {
auto shapeBufferCast = reinterpret_cast<sd::LongType*>(shapeBuffer);
auto type = sd::ArrayOptions::dataType(shapeBufferCast);
BUILD_SINGLE_SELECTOR(type, return _numpyHeaderLengthWordSize, (shapeBuffer, wordSize), SD_COMMON_TYPES);
return 0;
}
long numpyHeaderLength(OpaqueDataBuffer *opaqueDataBuffer,sd::Pointer shapeBuffer) {
auto shapeBufferCast = reinterpret_cast<sd::LongType*>(shapeBuffer);
auto type = sd::ArrayOptions::dataType(shapeBufferCast);
BUILD_SINGLE_SELECTOR(type, return _numpyHeaderLength, (opaqueDataBuffer, shapeBuffer), SD_COMMON_TYPES);
return 0;
}
sd::Pointer numpyFromNd4j(sd::Pointer data, sd::Pointer shapeBuffer, sd::LongType wordSize) {
auto shapeBufferCast = reinterpret_cast<sd::LongType*>(shapeBuffer);
auto type = sd::ArrayOptions::dataType(shapeBufferCast);
BUILD_SINGLE_SELECTOR(type, return _numpyFromNd4j, (data, shapeBuffer, wordSize), SD_COMMON_TYPES);
return nullptr;
}
sd::Pointer shapeBufferForNumpy(sd::Pointer npyArray) {
try {
cnpy::NpyArray arr = cnpy::loadNpyFromPointer(reinterpret_cast<char *>(npyArray));
unsigned int shapeSize = arr.shape.size();
std::vector<sd::LongType> shape(shapeSize);
bool _empty = false;
for (unsigned int i = 0; i < shapeSize; i++) {
shape[i] = arr.shape[i];
if (arr.shape[i] == 0) _empty = true;
}
auto dtype = cnpy::dataTypeFromHeader(reinterpret_cast<char *>(npyArray));
sd::LongType *shapeBuffer;
if (shape.size() == 1 && shape[0] == 0) {
// scalar case
shapeBuffer = sd::ShapeBuilders::createScalarShapeInfo(dtype);
} else if (_empty) {
if (shapeSize > 0)
shapeBuffer = sd::ShapeBuilders::emptyShapeInfo(dtype, arr.fortranOrder ? 'f' : 'c', shape);
else
shapeBuffer = sd::ShapeBuilders::emptyShapeInfo(dtype);
} else {
shapeBuffer = sd::ShapeBuilders::createShapeInfo(dtype, arr.fortranOrder ? 'f' : 'c', shape);
}
return (sd::Pointer)(sd::ConstantShapeHelper::getInstance().createFromExisting(
shapeBuffer)); // TO DO: this can lead to unpleasant crash sometimes
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return nullptr;
}
}
OpaqueNDArray getOutputArrayNative(OpaqueContext* ptr, int idx) {
if(ptr == nullptr)
return nullptr;
return ptr->outputArray(idx);
}
OpaqueNDArray getInputArrayNative(OpaqueContext* ptr, int idx) {
if(ptr == nullptr)
return nullptr;
return ptr->array(idx);
}
sd::LongType dataTypeNativeAt(OpaqueContext* ptr, int idx) {
if(ptr == nullptr)
return 0;
return static_cast<sd::LongType>(ptr->dataType(idx));
}
bool bArgAtNative(OpaqueContext* ptr, int idx) {
if(ptr == nullptr)
return false;
return ptr->getBArguments()->at(idx);
}
sd::LongType iArgumentAtNative(OpaqueContext* ptr, int idx) {
if(ptr == nullptr)
return 0;
return ptr->getIArguments()->at(idx);
}
sd::LongType numDNative(OpaqueContext* ptr) {
if(ptr == nullptr)
return 0;
return ptr->numD();
}
sd::LongType numBNative(OpaqueContext* ptr) {
if(ptr == nullptr)
return 0;
return ptr->numB();
}
sd::LongType numOutputsNative(OpaqueContext* ptr) {
if(ptr == nullptr)
return 0;
return ptr->outputWidth();
}
sd::LongType numInputsNative(OpaqueContext* ptr) {
if(ptr == nullptr)
return 0;
return ptr->width();
}
double tArgumentNative(OpaqueContext* ptr, int idx) {
if(ptr == nullptr)
return 0.0;
return ptr->getTArguments()->at(idx);
}
sd::LongType numTArgumentsNative(OpaqueContext* ptr) {
if(ptr == nullptr)
return 0;
return ptr->numT();
}
sd::LongType numIArgumentsNative(OpaqueContext* ptr) {
if(ptr == nullptr)
return 0;
return ptr->numI();
}
void setGraphContextOutputArray(OpaqueContext* ptr, int index,OpaqueNDArray arr) {
if(arr == nullptr)
THROW_EXCEPTION("setGraphContextOutputArray: Input arrays were null!");
ptr->setOutputArray(index,arr,false);
}
void setGraphContextInputArray(OpaqueContext* ptr,int index,OpaqueNDArray arr) {
if(arr == nullptr)
THROW_EXCEPTION("setGraphContextInputArray: Input arrays were null!");
ptr->setInputArray(index, arr, false);
}
//note here for javacpp mapping we have to use this odd type alias as a pointer
//to make the typedef work properly.
void setGraphContextOutputArraysArr(OpaqueContext* ptr, int numArrays,OpaqueNDArrayArr *arr) {
if (arr == nullptr) THROW_EXCEPTION("setGraphContextOutputArraysArr: Input arrays were null!");
for (int i = 0; i < numArrays; i++) {
if (arr[i] == nullptr) {
std::string errorMessage;
errorMessage += "setGraphContextOutputArraysArr: Input array at index ";
errorMessage += std::to_string(i);
errorMessage += " was null!";
THROW_EXCEPTION(errorMessage.c_str());
}
for (int j = 0; j < numArrays; j++) {
ptr->setOutputArray(j, *arr[j], false);
}
}
}
sd::Pointer createUtf8String(sd::Pointer *extraPointers, const char *string, int length) {
auto u = new sd::utf8string(string, length);
return reinterpret_cast<sd::Pointer>(u);
}
sd::LongType getUtf8StringLength(sd::Pointer *extraPointers, sd::Pointer ptr) {
return reinterpret_cast<sd::utf8string *>(ptr)->_length;
}
char *getUtf8StringBuffer(sd::Pointer *extraPointers, sd::Pointer ptr) {
return reinterpret_cast<sd::utf8string *>(ptr)->_buffer;
}
void deleteUtf8String(sd::Pointer *extraPointers, sd::Pointer ptr) { delete (reinterpret_cast<sd::utf8string *>(ptr)); }
int dataTypeFromNpyHeader(void *header) { return (int)cnpy::dataTypeFromHeader(reinterpret_cast<char *>(header)); }
OpaqueConstantShapeBuffer shapeBufferEx(int rank, sd::LongType *shape, sd::LongType *strides, sd::DataType dtype,
char order,
sd::LongType ews, sd::LongType extras) {
auto desc = sd::ShapeBuilders::createShapeInfo(dtype, order,rank, shape, strides,nullptr, extras);
auto buffer = sd::ConstantShapeHelper::getInstance().bufferForShapeInfo(desc);
return buffer;
}
void inspectArray(sd::Pointer *extraPointers, sd::Pointer buffer, sd::LongType *shapeInfo, sd::Pointer specialBuffer,
sd::LongType *specialShapeInfo, sd::Pointer debugInfo) {
try {
auto p = reinterpret_cast<sd::DebugInfo *>(debugInfo);
sd::NDArray array(buffer, shapeInfo, nullptr, 0, 0);
sd::DebugHelper::retrieveDebugStatistics(p, &array);
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
THROW_EXCEPTION(e.what());
}
}
void deleteConstantShapeBuffer(OpaqueConstantShapeBuffer *ptr) { }
void deleteConstantDataBuffer(OpaqueConstantDataBuffer *ptr) {
delete ptr;
}
OpaqueConstantShapeBuffer cacheAndStoreShapeBuffer(sd::LongType *shapeInfo) {
try {
auto buffer = sd::ConstantShapeHelper::getInstance().bufferForShapeInfo(shapeInfo);
return buffer;
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
THROW_EXCEPTION(e.what());
}
return nullptr;
}
sd::LongType *mmapFile(sd::Pointer *extraPointers, const char *fileName, sd::LongType length) {
auto hZ = new sd::LongType[2];
sd::LongType ptr = 0;
errno = 0;
try {
#if defined(_WIN32) || defined(_WIN64)
_mmap(hZ, static_cast<size_t>(length), fileName);
_mmap(hZ, static_cast<size_t>(length), fileName);
#else
int fd = open(fileName, O_RDWR, 0); // checking for failed fopen
if (fd < 0) {
sd_printf("Errno: %i\n", errno);
THROW_EXCEPTION("Failed to open file for MMAP");
}
void *ptr2 = mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0);
if (ptr2 == MAP_FAILED) {
sd_printf("Errno: %i\n", errno);
THROW_EXCEPTION("Failed to mmap file");
}
hZ[0] = (sd::LongType)ptr2;
hZ[1] = fd;
#endif
return hZ;
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
THROW_EXCEPTION(e.what());
}
return nullptr;
}
void munmapFile(sd::Pointer *extraPointers, sd::LongType *ptrMap, sd::LongType length) {}
ResultWrapper *executeFlatGraph(sd::Pointer *extraPointers, sd::Pointer flatBufferPointer) {
try {
return sd::graph::GraphExecutioner::executeFlatBuffer(flatBufferPointer);
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return nullptr;
}
}
sd::LongType getResultWrapperSize(ResultWrapper *ptr) { return ptr->size(); }
sd::Pointer getResultWrapperPointer(ResultWrapper *ptr) { return ptr->pointer(); }
const char *getAllCustomOps() { return sd::ops::OpRegistrator::getInstance().getAllCustomOperations(); }
OpaqueShapeList *calculateOutputShapes2(sd::Pointer *extraPointers, sd::LongType hash, OpaqueContext *context) {
try {
auto op = sd::ops::OpRegistrator::getInstance().getOperation(hash);
sd::ShapeList inShapes;
for (size_t e = 0; e < context->width(); e++) {
if (context->array(e) == nullptr) {
std::string errorMessage = "Input array at index " + std::to_string(e) + " was null!";
THROW_EXCEPTION(errorMessage.c_str());
}
inShapes.push_back(context->array(e)->shapeInfo());
}
auto shapeList = op->calculateOutputShape(&inShapes, *context);
return shapeList;
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return nullptr;
}
}
bool checkOpaqueNDArrayElementsNull(OpaqueNDArrayArr elements,int numElements) {
for (int i = 0; i < numElements; i++) {
if (elements[i] == nullptr) return true;
}
return false;
}
sd::LongType getShapeListSize(sd::ShapeList *list) { return list->size(); }
sd::LongType const *getShape(sd::ShapeList *list, sd::LongType i) { return list->at(i); }
// Function to execute a custom operation
sd::Status execCustomOp(sd::Pointer *extraPointers, sd::LongType hash, OpaqueNDArrayArr inputs, int numInputs,
OpaqueNDArrayArr outputs, int numOutputs, double *tArgs, int numTArgs,
sd::LongType *iArgs, int numIArgs, bool *bArgs, int numBArgs, bool isInplace) {
try {
// Convert NDArray** inputs and outputs to std::vector<NDArray*>
const std::vector<sd::NDArray*> inputVec(inputs, inputs + numInputs);
const std::vector<sd::NDArray*> outputVec(outputs, outputs + numOutputs);
const std::vector<double> tArgsVec(tArgs, tArgs + numTArgs);
const std::vector<sd::LongType > iArgsVec(iArgs, iArgs + numIArgs);
const std::vector<bool> bArgsVec(bArgs, bArgs + numBArgs);
// Retrieve the operation based on the hash
auto op = sd::ops::OpRegistrator::getInstance().getOperation(hash);
if (op == nullptr) {
throw std::invalid_argument("Operation not found for the given hash.");
}
// Execute the custom operation
return op->execute(inputVec, outputVec, tArgsVec, iArgsVec, bArgsVec, {}, isInplace);
}
catch (std::exception &e) {
// Handle exceptions by setting error codes and messages
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return sd::Status::KERNEL_FAILURE;
}
}
void toggleOpTrace(bool opTrace) { sd::ops::OpRegistrator::getInstance().toggleTraceOps(opTrace);
}
void purgeOpTrace() { sd::ops::OpRegistrator::getInstance().purgeOpExecs();
}
void printOpTrace() {
auto execTrace = *sd::ops::OpRegistrator::getInstance().execTrace();
for(size_t i = 0; i < execTrace.size(); i++) {
auto curr = execTrace[i];
if(curr->opName != nullptr) {
sd_printf("Op name: %s\n", curr->opName->c_str());
}
sd_printf(" Input buffers:\n",0);
if(curr->inputShapeBuffers == nullptr || curr->inputShapeBuffers->size() == 0) {
sd_printf("No input buffers\n",0);
continue;
} else {
auto currInputShapeBuffers = *(curr->inputShapeBuffers);
for(size_t j = 0; j < currInputShapeBuffers.size(); j++) {
auto buff = currInputShapeBuffers[j];
shape::printShapeInfo(buff);
sd_printf("\n",0);
}
}
if(curr->outputShapeBuffers == nullptr || curr->outputShapeBuffers->size() == 0) {
sd_printf("No output buffers\n",0);
continue;
} else {
auto currOutputShapeBuffers = *(curr->outputShapeBuffers);
for(size_t j = 0; j < curr->outputShapeBuffers->size(); j++) {
shape::printShapeInfo(currOutputShapeBuffers[j]);
sd_printf("\n",0);
}
}
}
}
std::vector<ExecTrace*> * listOpTraces() {
return sd::ops::OpRegistrator::getInstance().execTrace();
}
void deleteNDArray(OpaqueNDArray array) {
delete array;
}
sd::LongType getOpaqueNDArrayOffset(OpaqueNDArray array) {
return array->offset();
}
const sd::LongType* getOpaqueNDArrayShapeInfo(OpaqueNDArray array) {
return array->shapeInfo();
}
void* getOpaqueNDArrayBuffer(OpaqueNDArray array) {
if(array == nullptr || array->dataBuffer() == nullptr) {
THROW_EXCEPTION("getOpaqueNDArrayBuffer: Array or data buffer was null!");
}
return array->dataBuffer()->primary();
}
void* getOpaqueNDArraySpecialBuffer(OpaqueNDArray array) {
if(array == nullptr || array->dataBuffer() == nullptr) {
THROW_EXCEPTION("getOpaqueNDArraySpecialBuffer: Array or data buffer was null!");
}
return array->dataBuffer()->special();
}
sd::LongType getShapeInfoLength(OpaqueNDArray array) {
return shape::shapeInfoLength(array->rankOf());
}
sd::LongType getOpaqueNDArrayLength(OpaqueNDArray array) {
return array->dataBuffer()->getNumElements();
}
OpaqueNDArray createOpaqueNDArray(OpaqueDataBuffer *shapeInfo,
OpaqueDataBuffer *buffer,
OpaqueDataBuffer *specialBuffer,
sd::LongType offset) {
if(shapeInfo == nullptr) {
THROW_EXCEPTION("createOpaqueNDArray: Shape info was null!");
}
if(shape::isEmpty(static_cast<sd::LongType *>(
shapeInfo->primary())) && buffer != nullptr) {
THROW_EXCEPTION("createOpaqueNDArray: Shape info was empty but buffer was not null!");
} else if(!shape::isEmpty(static_cast<sd::LongType *>(
shapeInfo->primary())) && buffer == nullptr) {
THROW_EXCEPTION("createOpaqueNDArray: Shape info was empty but buffer was not null!");
}
sd::LongType* shapeInfoCast = reinterpret_cast<sd::LongType*>(shapeInfo->primary());
sd::NDArray* ret = new sd::NDArray(buffer != nullptr ? buffer->getDataBuffer() : nullptr,
shapeInfoCast,
sd::LaunchContext::defaultContext(),
offset);
return ret;
}
void copyBuffer(OpaqueDataBuffer *target, long n, OpaqueDataBuffer *from, long fromOffset, long targetOffset) {
sd::DataBuffer::memcpy(target->dataBuffer(), from->dataBuffer(), targetOffset, fromOffset);
}
int contextNumInputs(void *contextPointer) {
Context *context = (Context *) contextPointer;
return context->width();
}
int contextNumOutputs(void *contextPointer) {
Context *context = (Context *) contextPointer;
return context->outputWidth();
}
int numInputs(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return trace->inputShapeBuffers->size();
}
int numOutputs(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return trace->outputShapeBuffers->size();
}
std::vector<bool> * bArgs(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return &trace->bArgs;
}
std::vector<std::string> * sArgs(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return (&trace->sArguments);
}
std::vector<double> * tArgs(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return (&trace->tArgs);
}
std::vector<int> * dArgs(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
std::vector<int> *dArgs = new std::vector<int>();
for (size_t e = 0; e < trace->dArgs.size(); e++) {
dArgs->push_back(trace->dArgs[e]);
}
return dArgs;
}
std::vector<sd::LongType> * iArgs(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return &(trace->iArgs);
}
std::vector<const sd::LongType *> *inputShapeBuffers(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return trace->inputShapeBuffers;
}
std::vector<const sd::LongType *> *outputShapeBuffers(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return trace->outputShapeBuffers;
}
char *opName(void *execTrace) {
ExecTrace *trace = (ExecTrace *) execTrace;
return const_cast<char *>(trace->opName->c_str());
}
void setElementThreshold(int num) {
if (num > 0) sd::Environment::getInstance().setElementwiseThreshold(num);
}
void setTADThreshold(int num) {
if (num > 0) sd::Environment::getInstance().setTadThreshold(num);
}
sd::Status registerGraph(sd::Pointer *extraPointers, sd::LongType graphId, sd::Pointer flatBufferPointer) {
try {
auto graph = sd::graph::GraphExecutioner::importFromFlatPointer(flatBufferPointer);
GraphHolder::getInstance().registerGraph(graphId, graph);
return sd::Status::OK;
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return sd::Status::BAD_INPUT;
}
}
static VariablesSet *executeStoredGraphT(sd::Pointer *extraPointers, sd::LongType graphId, sd::Pointer *inputBuffers,
sd::Pointer *inputShapes, int *inputIndices, int numInputs) {
auto graph = sd::graph::GraphHolder::getInstance().cloneGraph(graphId);
auto varSpace = graph->getVariableSpace();
std::vector<sd::NDArray *> handles;
for (int e = 0; e < numInputs; e++) {
auto idx = inputIndices[e];
// we'll delete this array later, together with cloned VariableSpace
auto array = new sd::NDArray(inputBuffers[e], reinterpret_cast<sd::LongType *>(inputShapes[e]), nullptr, 0, 0);
handles.emplace_back(array);
if (varSpace->hasVariable(idx)) {
auto var = varSpace->getVariable(idx);
if (var->hasNDArray()) delete var->getNDArray();
var->setNDArray(array);
} else
varSpace->putVariable(idx, array);
}
auto hZ = sd::graph::GraphExecutioner::execute(graph, varSpace);
auto varSet = new sd::graph::VariablesSet(hZ);
if (hZ == sd::Status::OK) {
// pull back results, and provide them
auto outputs = graph->fetchOutputs();
int size = static_cast<int>(outputs->size());
for (int e = 0; e < size; e++) {
// we're only getting variable ID/Index from original grap. values will be taken from cloned workspace
std::pair<int, int> varId(outputs->at(e)->id(), outputs->at(e)->index());
auto var = varSpace->getVariable(varId);
varSet->push_back(var->clone());
}
delete outputs;
}
delete graph;
return varSet;
}
VariablesSet *executeStoredGraph(sd::Pointer *extraPointers, sd::LongType graphId, sd::Pointer *inputBuffers, sd::Pointer *inputShapes,
int *inputIndices, int numInputs) {
try {
return executeStoredGraphT(extraPointers, graphId, inputBuffers, inputShapes, inputIndices, numInputs);
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return nullptr;
}
}
sd::LongType getVariablesSetSize(OpaqueVariablesSet *set) { return set->size(); }
sd::Status getVariablesSetStatus(OpaqueVariablesSet *set) { return set->status(); }
OpaqueVariable *getVariable(OpaqueVariablesSet *set, sd::LongType i) { return set->at(i); }
int getVariableId(Variable *variable) { return variable->id(); }
int getVariableIndex(Variable *variable) { return variable->index(); }
const char *getVariableName(Variable *variable) { return variable->getName()->c_str(); }
sd::LongType const *getVariableShape(Variable *variable) { return variable->getNDArray()->shapeInfo(); }
void *getVariableBuffer(Variable *variable) { return variable->getNDArray()->buffer(); }
sd::Status unregisterGraph(sd::Pointer *extraPointers, sd::LongType graphId) {
try {
GraphHolder::getInstance().dropGraphAny(graphId);
return sd::Status::OK;
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return sd::Status::BAD_INPUT;
}
}
void deletePointerArray(sd::Pointer pointer) {
sd::Pointer *ptr = reinterpret_cast<sd::Pointer *>(pointer);
delete[] ptr;
}
void deleteCharArray(sd::Pointer pointer) {
auto ptr = reinterpret_cast<char *>(pointer);
delete[] ptr;
}
void deleteIntArray(sd::Pointer pointer) {
auto ptr = reinterpret_cast<int *>(pointer);
delete[] ptr;
}
void deleteLongArray(sd::Pointer pointer) {
auto ptr = reinterpret_cast<sd::LongType *>(pointer);
delete[] ptr;
}
void deleteVariablesSet(VariablesSet *pointer) {
delete pointer;
}
void deleteShapeList(sd::Pointer shapeList) {
sd::ShapeList *list = reinterpret_cast<sd::ShapeList *>(shapeList);
delete list;
}
const char *getAllOperations() { return sd::OpTracker::getInstance().exportOperations(); }
sd::Pointer getGraphState(sd::LongType id) { return (sd::Pointer) new GraphState(id); }
void deleteGraphState(sd::Pointer state) {
auto stateP = reinterpret_cast<GraphState *>(state);
delete stateP;
}
sd::Status execCustomOpWithScope_(sd::Pointer *extraPointers, sd::graph::GraphState *state, sd::LongType opHash,
sd::LongType *scopes, int numScopes, sd::Pointer *inputBuffers,
sd::Pointer *inputShapes, int numInputs, sd::Pointer *outputBuffers,
sd::Pointer *outputShapes, int numOutputs) {
/**
* That's basically exec, with VariableSpace provided in GraphState:
* depending on operation (i.e. while of if), different logic executors could be used
*/
auto graph = state->graph();
auto varSpace = state->variableSpace();
// Node is dynamically created, and has nothing beyond it: only inputs and outputs
// this node has id of 0, and inputs are
Node node(::graph::OpType_LOGIC, opHash, 0);
// mapping inputs
for (int e = 0; e < numInputs; e++) {
auto buffer = inputBuffers[e];
auto shapeInfo = reinterpret_cast<sd::LongType *>(inputShapes[e]);
auto array = new sd::NDArray(buffer, shapeInfo, varSpace->launchContext(), 0, 0);
// now we just put array to VarSpace
varSpace->putVariable(0, e, *array);
node.pickInput(0, e);
}
// mapping scopes
for (int e = 0; e < numScopes; e++) {
// we should check scope existence in GraphState/Graph
int scopeId = (int)scopes[e];
if (!state->hasScope(scopeId)) {
return sd::Logger::logKernelFailureMsg();
}
node.pickInput(scopeId, 0);
}
auto hZ = LogicExecutor::processNode(graph, &node);
if (hZ != sd::Status::OK) return hZ;
// mapping outputs
for (int e = 0; e < numOutputs; e++) {
auto buffer = outputBuffers[e];
auto shapeInfo = reinterpret_cast<sd::LongType *>(outputShapes[e]);
sd::NDArray array(buffer, shapeInfo, varSpace->launchContext(), 0, 0);
// now we just put array to VarSpace to the same ID
// varSpace->putVariable(0, e, array);
auto t = varSpace->getVariable(0, e)->getNDArray();
array.assign(t);
}
// removing input variables
for (int e = 0; e < numInputs; e++) {
varSpace->dropVariable(0, e);
}
return sd::Status::OK;
}
void deleteResultWrapper(sd::Pointer ptr) {
auto p = reinterpret_cast<ResultWrapper *>(ptr);
delete p;
}
template <typename T>
SD_INLINE int estimateThresholdGeneric(sd::Pointer *extraPointers, sd::Pointer hX, int N, float threshold) {
auto buffer = reinterpret_cast<T *>(hX);
int span = (N / 6) + 8;
// Cast the threshold to the appropriate type T
T typedThreshold = static_cast<T>(threshold);
auto func = PRAGMA_REDUCE_LONG {
int64_t cnt = 0;
PRAGMA_OMP_SIMD
for (auto e = start; e < stop; e++) {
auto v = sd::math::sd_abs<T,T>(buffer[e]);
if (v >= typedThreshold) cnt++;
}
return cnt;
};
return samediff::Threads::parallel_long(
func, LAMBDA_AL { return _old + _new; }, 0, N);
}
int estimateThreshold(sd::Pointer *extraPointers, sd::Pointer hX, sd::LongType const *hXShapeInfo, int N,
float threshold) {
try {
auto xType = sd::ArrayOptions::dataType(hXShapeInfo);
BUILD_SINGLE_SELECTOR(xType, return estimateThresholdGeneric, (extraPointers, hX, N, threshold), SD_FLOAT_TYPES);
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return 0;
}
return 0;
}
void deleteTadPack(sd::TadPack *ptr) {
delete ptr;
}
OpaqueConstantDataBuffer constantBufferLong(sd::DataType dtype, sd::LongType *data, int length) {
return sd::ConstantHelper::getInstance().constantBuffer(sd::ConstantDescriptor(data, length), dtype);
}
OpaqueConstantDataBuffer constantBufferDouble(sd::DataType dtype, double *data, int length) {
return sd::ConstantHelper::getInstance().constantBuffer(sd::ConstantDescriptor(data, length), dtype);
}
OpaqueConstantDataBuffer constantBuffer(sd::DataType dtype, sd::ConstantDescriptor *descriptor) {
return sd::ConstantHelper::getInstance().constantBuffer(*descriptor, dtype);
}
sd::Pointer getConstantDataBufferPrimary(OpaqueConstantDataBuffer dbf) { return dbf->primary(); }
sd::Pointer getConstantDataBufferSpecial(OpaqueConstantDataBuffer dbf) { return dbf->special(); }
sd::LongType getConstantDataBufferLength(OpaqueConstantDataBuffer dbf) { return dbf->length(); }
sd::LongType getConstantDataBufferSizeOf(OpaqueConstantDataBuffer dbf) { return dbf->sizeOf(); }
sd::Pointer getConstantShapeBufferPrimary(OpaqueConstantShapeBuffer dbf) { return const_cast<sd::LongType *>(dbf->primary()); }
sd::Pointer getConstantShapeBufferSpecial(OpaqueConstantShapeBuffer dbf) { return const_cast<sd::LongType *>(dbf->special()); }
Context *createGraphContext(int nodeId) { return new Context(nodeId); }
OpaqueRandomGenerator getGraphContextRandomGenerator(Context *ptr) { return &ptr->randomGenerator(); }
void markGraphContextInplace(Context *ptr, bool reallyInplace) { ptr->markInplace(reallyInplace); }
//note here for javacpp mapping we have to use this odd type alias as a pointer
//to make the typedef work properly.
void setGraphContextInputArraysArr(OpaqueContext* ptr, int numArrays,OpaqueNDArrayArr *arr) {
if(arr == nullptr)
THROW_EXCEPTION("setGraphContextInputArraysArr: Input arrays were null!");
for (int i = 0; i < numArrays; i++) {
if(arr[i] == nullptr) {
std::string errorMessage;
errorMessage += "setGraphContextInputArraysArr: Input array at index ";
errorMessage += std::to_string(i);
errorMessage += " was null!";
THROW_EXCEPTION(errorMessage.c_str());
}
OpaqueNDArray &ref = *arr[i];
ptr->setInputArray(i, ref, false);
}
}
void setGraphContextTArguments(Context *ptr, double *arguments, int numberOfArguments) {
ptr->setTArguments(arguments, numberOfArguments);
}
void setGraphContextIArguments(Context *ptr, sd::LongType *arguments, int numberOfArguments) {
ptr->setIArguments(arguments, numberOfArguments);
}
void setGraphContextBArguments(Context *ptr, bool *arguments, int numberOfArguments) {
ptr->setBArguments(arguments, numberOfArguments);
}
void setGraphContextDArguments(OpaqueContext *ptr, int *arguments, int numberOfArguments) {
std::vector<sd::DataType> dtypes(numberOfArguments);
for (int e = 0; e < numberOfArguments; e++) dtypes[e] = sd::DataTypeUtils::fromInt(arguments[e]);
ptr->setDArguments(dtypes);
}
void deleteGraphContext(Context *ptr) {}
OpaqueRandomGenerator createRandomGenerator(sd::LongType rootSeed, sd::LongType nodeSeed) {
try {
return new RandomGenerator(rootSeed, nodeSeed);
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return nullptr;
}
}
sd::LongType getRandomGeneratorRootState(OpaqueRandomGenerator ptr) { return ptr->rootState(); }
sd::LongType getRandomGeneratorNodeState(OpaqueRandomGenerator ptr) { return ptr->nodeState(); }
void setRandomGeneratorStates(OpaqueRandomGenerator ptr, sd::LongType rootSeed, sd::LongType nodeSeed) {
ptr->setStates(rootSeed, nodeSeed);
}
float getRandomGeneratorRelativeFloat(OpaqueRandomGenerator ptr, sd::LongType index) {
return ptr->relativeT<float>(index);
}
double getRandomGeneratorRelativeDouble(OpaqueRandomGenerator ptr, sd::LongType index) {
return ptr->relativeT<double>(index);
}
int getRandomGeneratorRelativeInt(OpaqueRandomGenerator ptr, sd::LongType index) { return ptr->relativeInt(index); }
sd::LongType getRandomGeneratorRelativeLong(OpaqueRandomGenerator ptr, sd::LongType index) {
return ptr->relativeLong(index);
}
int getRandomGeneratorNextInt(OpaqueRandomGenerator ptr) {
// to nullify _nodeState._long ^= (steps ^ 0xdeadbeef);
// we will use step = 0xdeadbeef
auto result = ptr->relativeInt(1);
ptr->rewindH(0xdeadbeef);
return result;
}
sd::LongType getRandomGeneratorNextLong(OpaqueRandomGenerator ptr) {
auto result = ptr->relativeLong(1);
ptr->rewindH(0xdeadbeef);
return result;
}
float getRandomGeneratorNextFloat(OpaqueRandomGenerator ptr) {
auto result = ptr->relativeT<float>(1);
ptr->rewindH(0xdeadbeef);
return result;
}
double getRandomGeneratorNextDouble(OpaqueRandomGenerator ptr) {
auto result = ptr->relativeT<double>(1);
ptr->rewindH(0xdeadbeef);
return result;
}
void deleteRandomGenerator(OpaqueRandomGenerator ptr) { delete ptr; }
/**
* Get the shape buffer from a
* numpy array.
* **Warning** this allocates memory
* @param npyArray
* @return
*/
sd::Pointer shapeBufferForNumpyHeader(sd::Pointer npyArray) {
cnpy::NpyArray arr = cnpy::loadNpyFromHeader(reinterpret_cast<char*>(npyArray));
auto shape = new sd::LongType[arr.shape.size()];
for (unsigned int i = 0; i < arr.shape.size(); i++) {
shape[i] = arr.shape[i];
}
auto shapeBuffer = shape::shapeBufferOfNpy(arr.shape.size(), shape, arr.fortranOrder);
delete[] shape;
return reinterpret_cast<sd::Pointer>(shapeBuffer);
}
/**
*
* @param npyArray
* @return
*/
sd::Pointer dataPointForNumpyHeader(sd::Pointer npyArray) {
cnpy::NpyArray arr = cnpy::loadNpyFromHeader(reinterpret_cast<char*>(npyArray));
unsigned char* dataToPrint = reinterpret_cast<unsigned char*>(arr.data);
return dataToPrint;
}
/**
*
* @param npyArray
* @return
*/
sd::Pointer dataPointForNumpyStruct(sd::Pointer npyArrayStruct) {
cnpy::NpyArray* arrPointer = reinterpret_cast<cnpy::NpyArray*>(npyArrayStruct);
unsigned char* dataToPrint = reinterpret_cast<unsigned char*>(arrPointer->data);
return reinterpret_cast<sd::Pointer>(dataToPrint);
}
/**
*
* @param npyArray
* @param fromFile
* @return
*/
sd::Pointer dataPointForNumpy(sd::Pointer npyArray) {
char* npyArrayBuffer = reinterpret_cast<char*>(npyArray);
cnpy::NpyArray arr = cnpy::loadNpyFromPointer(npyArrayBuffer);
return dataPointForNumpyStruct(reinterpret_cast<sd::Pointer>(&arr));
}
/**
* Load a numpy array from a file
* and return it as an sd::Pointer
* @param path
* @return
*/
sd::Pointer numpyFromFile(std::string path) {
char* numpyBuffer = cnpy::loadFile(path.data());
return reinterpret_cast<sd::Pointer>(numpyBuffer);
}
////// NPZ //////
void* mapFromNpzFile(std::string path) {
cnpy::npz_t* mapPtr = new cnpy::npz_t();
cnpy::npz_t map = cnpy::npzLoad(path);
mapPtr->insert(map.begin(), map.end());
return reinterpret_cast<void*>(mapPtr);
}
int getNumNpyArraysInMap(void* map) {
cnpy::npz_t* arrays = reinterpret_cast<cnpy::npz_t*>(map);
int n = arrays->size();
return n;
}
const char* getNpyArrayNameFromMap(void* map, int index, char* nameBuffer) {
cnpy::npz_t* arrays = reinterpret_cast<cnpy::npz_t*>(map);
cnpy::npz_t::iterator it = arrays->begin();
cnpy::npz_t::iterator end = arrays->end();
int cnt = 0;
for (; it != end; ++it, ++cnt) {
if (cnt == index) {
size_t len_of_str = strlen(it->first.c_str());
memcpy(nameBuffer, it->first.c_str(), len_of_str);
}
}
return "";
}
void* getNpyArrayFromMap(void* map, int index) {
cnpy::npz_t* arrays = reinterpret_cast<cnpy::npz_t*>(map);
cnpy::npz_t::iterator it = arrays->begin();
cnpy::npz_t::iterator end = arrays->end();
cnpy::NpyArray* arr = new cnpy::NpyArray();
int cnt = 0;
for (; it != end; ++it, ++cnt) {
if (cnt == index) {
*arr = it->second;
return arr;
}
}
return nullptr;
}
void* getNpyArrayData(void* npArray) {
cnpy::NpyArray* npyArray2 = reinterpret_cast<cnpy::NpyArray*>(npArray);
return reinterpret_cast<void*>(npyArray2->data);
}
int getNpyArrayRank(void* npArray) {
cnpy::NpyArray* arr = reinterpret_cast<cnpy::NpyArray*>(npArray);
int rank = arr->shape.size();
return rank;
}
sd::LongType* getNpyArrayShape(void* npArray) {
cnpy::NpyArray* arr = reinterpret_cast<cnpy::NpyArray*>(npArray);
int ndim = arr->shape.size();
sd::LongType* shape = new sd::LongType[ndim];
for (int i = 0; i < ndim; i++) {
shape[i] = arr->shape.at(i);
}
return shape;
}
char getNpyArrayOrder(void* npArray) {
cnpy::NpyArray* arr = reinterpret_cast<cnpy::NpyArray*>(npArray);
return (arr->fortranOrder) ? 'f' : 'c';
}
int getNpyArrayElemSize(void* npArray) {
cnpy::NpyArray* arr = reinterpret_cast<cnpy::NpyArray*>(npArray);
return arr->wordSize;
}
void deleteNPArrayStruct(void* npArray) {
cnpy::NpyArray* arr = reinterpret_cast<cnpy::NpyArray*>(npArray);
delete arr;
}
void deleteNPArrayMap(void* map) {
cnpy::npz_t* arrays = reinterpret_cast<cnpy::npz_t*>(map);
delete arrays;
}
//////
/**
* Get the element size for a numpy array
* @param npyArray the numpy array's address
* to get the length for
* @return
*/
int elementSizeForNpyArray(sd::Pointer npyArray) {
cnpy::NpyArray arr = cnpy::loadNpyFromPointer(reinterpret_cast<char*>(npyArray));
cnpy::NpyArray* arrPointer = &arr;
int size = arrPointer->wordSize;
// arrPointer->destruct();
return size;
}
/**
* Get the element size for a numpy array
* @param npyArray the numpy array's address
* to get the length for
* @return
*/
int elementSizeForNpyArrayHeader(sd::Pointer npyArray) {
cnpy::NpyArray arr = cnpy::loadNpyFromHeader(reinterpret_cast<char*>(npyArray));
cnpy::NpyArray* arrPointer = &arr;
int size = arrPointer->wordSize;
return size;
}
void releaseNumpy(sd::Pointer npyArray) { free(reinterpret_cast<void*>(npyArray)); }
#if defined(SD_GCC_FUNCTRACE)
// this is mainly a c based function.
extern "C" {
//note this is a c++ 17 feature
#ifndef INSTRUMENT_FILE_DEF
#define INSTRUMENT_FILE_DEF 1
FILE* instrumentFile = nullptr;
#endif
}
#endif
void ctxAllowHelpers(OpaqueContext *ptr, bool reallyAllow) { ptr->allowHelpers(reallyAllow); }
void ctxSetExecutionMode(OpaqueContext *ptr, int execMode) {
if (execMode < 0 || execMode > 2) execMode = 0;
ptr->setExecutionMode((samediff::ExecutionMode)execMode);
}
sd::LongType getCachedMemory(int deviceId) { return sd::ConstantHelper::getInstance().getCachedAmount(deviceId); }
void ctxShapeFunctionOverride(OpaqueContext *ptr, bool reallyOverride) {
ptr->setShapeFunctionOverride(reallyOverride);
}
void ctxPurge(OpaqueContext *ptr) { ptr->clearFastPath(); }
int lastErrorCode() { return sd::LaunchContext::defaultContext()->errorReference()->errorCode(); }
const char *lastErrorMessage() { return sd::LaunchContext::defaultContext()->errorReference()->errorMessage(); }
sd::LaunchContext *defaultLaunchContext() { return sd::LaunchContext::defaultContext(); }
void setIntermediateResult(OpaqueContext *contextPointer,
int index,
OpaqueDataBuffer *buffer,
OpaqueDataBuffer *shapeInfo,
sd::LongType dataOffset) {
if(shapeInfo == nullptr) {
THROW_EXCEPTION("Set Intermediate Result: shapeInfo is null");
}
auto casted = reinterpret_cast<sd::LongType *>(shapeInfo->primary());
auto desc = new sd::ShapeDescriptor(casted, false);
auto arr = new sd::NDArray(buffer->dataBuffer(),
desc,
sd::LaunchContext::defaultContext(),
dataOffset);
contextPointer->setIntermediateResult(index, arr);
}
std::vector<const sd::LongType *> intermediateResultsShapeInfo(OpaqueContext *contextPointer) {
std::vector<const sd::LongType *> intermediates;
for (auto v: contextPointer->intermediateResults()) {
const sd::LongType *buff = v->shapeInfo();
intermediates.push_back(buff);
}
return intermediates;
}
std::vector<OpaqueDataBuffer *> intermediateResults(OpaqueContext *contextPointer) {
std::vector<OpaqueDataBuffer *> intermediates;
for (auto v: contextPointer->intermediateResults()) {
OpaqueDataBuffer *buff = new OpaqueDataBuffer (v->dataBuffer());
intermediates.push_back(buff);
}
return intermediates;
}
int numIntermediateResults(OpaqueContext *contextPointer) {
return contextPointer->numIntermediates();
}
void pushIntermediateResult(OpaqueContext *contextPointer,
OpaqueDataBuffer *buffer,
OpaqueDataBuffer *shapeInfo,
sd::LongType offset) {
auto shapeInfoCast = reinterpret_cast<sd::LongType *>(shapeInfo->primary());
auto desc = new sd::ShapeDescriptor(shapeInfoCast, false);
auto arr = new sd::NDArray(buffer->dataBuffer(), desc, sd::LaunchContext::defaultContext(), offset);
contextPointer->pushIntermediateResult(arr);
}
OpaqueDataBuffer * intermediateResultDataAt(int index, OpaqueContext *contextPointer) {
auto arr = contextPointer->intermediateResult(index);
return new OpaqueDataBuffer(arr->dataBuffer());
}
const sd::LongType * intermediateResultShapeInfoAt(int index, OpaqueContext *contextPointer) {
auto context = reinterpret_cast<sd::graph::Context *>(contextPointer);
auto arr = context->intermediateResult(index);
return arr->shapeInfo();
}
sd::LongType const *getPrimaryShapeInfo(sd::TadPack *pack) {
return const_cast<sd::LongType *>(pack->primaryShapeInfo());
}
sd::LongType const *getPrimaryOffsets(sd::TadPack *pack) {
if(pack->primaryOffsets() == nullptr)
THROW_EXCEPTION("getPrimaryOffsets: primaryOffsets is nullptr!");
return const_cast<sd::LongType *>(pack->primaryOffsets());
}
sd::LongType const *getSpecialShapeInfo(sd::TadPack *pack) {
return const_cast<sd::LongType *>(pack->specialShapeInfo());
}
sd::LongType const *getSpecialOffsets(sd::TadPack *pack) { return const_cast<sd::LongType *>(pack->specialOffsets()); }
sd::LongType getNumberOfTads(sd::TadPack *pack) { return pack->numberOfTads(); }
int getShapeInfoLength(sd::TadPack *pack) { return pack->shapeInfoLength(); }
sd::TadPack *tadOnlyShapeInfo(OpaqueDataBuffer *hXShapeInfo, sd::LongType *dimension, sd::LongType dimensionLength) {
try {
if(hXShapeInfo->primary() == nullptr) {
THROW_EXCEPTION("tadOnlyShapeInfo: hXShapeInfo->primary() is nullptr!");
}
auto buffPrim = reinterpret_cast<sd::LongType *>(hXShapeInfo->primary());
auto shapeFromCache = sd::ConstantShapeHelper::getInstance().bufferForShapeInfo(buffPrim)->primary();
auto rankVal = shapeFromCache[0];
if(rankVal == 0) {
//detect when the shape buffer values are unset.
auto len = shape::shapeInfoLength(rankVal);
//min number of values in a shape info buffer
bool allZero = true;
for(int i = 0; i < len; i++) {
if(buffPrim[i] != 0) {
allZero = false;
break;
}
}
if(allZero) {
THROW_EXCEPTION("Found shape buffer with all zero values. Values likely unset.");
}
}
auto pack = sd::ConstantTadHelper::getInstance().tadForDimensions(
shapeFromCache, dimension, dimensionLength);
return pack;
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
THROW_EXCEPTION(e.what());
}
return nullptr;
}
OpaqueConstantShapeBuffer shapeBuffer(int rank, sd::LongType *shape, sd::LongType *strides, sd::DataType dtype,
char order, sd::LongType ews, bool empty) {
return shapeBufferEx(rank, shape, strides, dtype, order, ews, empty ? ARRAY_EMPTY : 0);
}
void dbPrintAllocationTrace(OpaqueDataBuffer *db) { db->dataBuffer()->printAllocationTrace(); }
sd::LongType dbBufferLength(OpaqueDataBuffer *dataBuffer) {
return dataBuffer->dataBuffer()->getNumElements();
}
OpaqueDataBuffer *dbAllocateDataBuffer(sd::LongType elements, int dataType, bool allocateBoth) {
return allocateDataBuffer(elements, dataType, allocateBoth);
}
OpaqueDataBuffer *allocateDataBuffer(sd::LongType elements, int dataType, bool allocateBoth) {
try {
auto dtype = sd::DataTypeUtils::fromInt(dataType);
sd::LongType totalElementSize = elements == 0 ? sd::DataTypeUtils::sizeOf(dtype) : elements * sd::DataTypeUtils::sizeOf(dtype);
return new sd::InteropDataBuffer(totalElementSize, dtype, allocateBoth);
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
return nullptr;
}
}
OpaqueDataBuffer *dbCreateExternalDataBuffer(sd::LongType elements, int dataType, sd::Pointer primary, sd::Pointer special) {
auto buffer = dbAllocateDataBuffer(0, dataType, false);
buffer->markOwner(false);
if (primary != nullptr) buffer->setPrimary(primary, elements);
if (special != nullptr) buffer->setSpecial(special, elements);
return buffer;
}
sd::Pointer dbPrimaryBuffer(OpaqueDataBuffer *dataBuffer) {
if (dataBuffer == nullptr) THROW_EXCEPTION("dbPrimaryBuffer: dataBuffer is null");
return dataBuffer->primary();
}
sd::Pointer dbSpecialBuffer(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbSpecialBuffer: dataBuffer is null");
return dataBuffer->special();
}
void deleteDataBuffer(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbPrimaryBuffer: dataBuffer is null");
delete dataBuffer;
}
void dbSetPrimaryBuffer(OpaqueDataBuffer *dataBuffer, sd::Pointer primaryBuffer, sd::LongType numBytes) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbSetPrimaryBuffer: dataBuffer is null");
dataBuffer->setPrimary(primaryBuffer, numBytes);
}
void dbSetSpecialBuffer(OpaqueDataBuffer *dataBuffer, sd::Pointer specialBuffer, sd::LongType numBytes) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbSetSpecialBuffer: dataBuffer is null");
dataBuffer->setSpecial(specialBuffer, numBytes);
}
void dbAllocatePrimaryBuffer(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbAllocatePrimaryBuffer: dataBuffer is null");
dataBuffer->dataBuffer()->allocatePrimary();
}
void dbAllocateSpecialBuffer(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbAllocateSpecialBuffer: dataBuffer is null");
dataBuffer->dataBuffer()->allocateSpecial();
}
void dbExpandBuffer(OpaqueDataBuffer *dataBuffer, sd::LongType elements) {
try {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbExpandBuffer: dataBuffer is null");
dataBuffer->dataBuffer()->expand(elements * sd::DataTypeUtils::sizeOf(dataBuffer->dataBuffer()->getDataType()));
} catch (std::exception &e) {
sd::LaunchContext::defaultContext()->errorReference()->setErrorCode(1);
sd::LaunchContext::defaultContext()->errorReference()->setErrorMessage(e.what());
}
}
OpaqueDataBuffer *dbCreateView(OpaqueDataBuffer *dataBuffer, sd::LongType length) {
return new OpaqueDataBuffer(dataBuffer, length);
}
int dbUseCount(OpaqueDataBuffer* dataBuffer) {
if(dataBuffer) return dataBuffer->useCount();
return 0;
}
void dbSyncToSpecial(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbSyncToSpecial: dataBuffer is null");
if(dataBuffer->dataBuffer() != nullptr && dataBuffer->dataBuffer()->getNumElements() > 0)
dataBuffer->dataBuffer()->syncToSpecial();
}
void dbSyncToPrimary(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbSyncToPrimary: dataBuffer is null");
if(dataBuffer->dataBuffer() != nullptr && dataBuffer->dataBuffer()->getNumElements() > 0)
dataBuffer->dataBuffer()->syncToPrimary(sd::LaunchContext::defaultContext(),false);
}
void dbTickHostRead(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbTickHostRead: dataBuffer is null");
dataBuffer->dataBuffer()->readPrimary();
}
void dbTickHostWrite(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbTickHostWrite: dataBuffer is null");
dataBuffer->dataBuffer()->writePrimary();
}
void dbTickDeviceRead(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbTickDeviceRead: dataBuffer is null");
dataBuffer->dataBuffer()->readSpecial();
}
void dbTickDeviceWrite(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbTickDeviceWrite: dataBuffer is null");
dataBuffer->dataBuffer()->writeSpecial();
}
void dbExpand(OpaqueDataBuffer *dataBuffer, sd::LongType elements) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbExpand: dataBuffer is null");
dataBuffer->expand(elements);
}
void dbClose(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbClose: dataBuffer is null");
auto ret = dataBuffer->getDataBuffer();
if(ret != nullptr)
dataBuffer->getDataBuffer()->close();
}
int dbDeviceId(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbDeviceId: dataBuffer is null");
return dataBuffer->deviceId();
}
void dbSetDeviceId(OpaqueDataBuffer *dataBuffer, int deviceId) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbSetDeviceId: dataBuffer is null");
dataBuffer->setDeviceId(deviceId);
}
int dbLocality(OpaqueDataBuffer *dataBuffer) {
if(dataBuffer == nullptr)
THROW_EXCEPTION("dbLocality: dataBuffer is null");
auto p = dataBuffer->dataBuffer()->isPrimaryActual();
auto d = dataBuffer->dataBuffer()->isSpecialActual();
if (p && d)
return 0;
else if (p)
return -1;
else
return 1;
}