Shugeo cuda cuda (#105)

* Refactored extract_image_patches op helpers.

* Eliminated compliler errors with helper implementation.

* Finished implementation for extract_image_patches both cpu and cuda helpers.

* Improved cpu implementation.

* Improved cuda implementation for extract_image_patches helper.

* Added omp to ClipByGlobalNorm helpers implementation.

* Added implementation for thresholedrelu_bp op.

* Fixed cuda kernel with F order.

* Fixed tests for subarray.

* Refactored tests for Gaussian_3 and Truncated_22.

* Added tests for GaussianDistribution with native ops.

* Modified tests for Gaussian distribution.

* Fixed random tests.

* Fixed atomicMin/atomicMax for 64bit cases.

* Fixed tests for execReduce3TAD tests.

* Eliminated waste comments.
master
shugeo 2019-08-07 15:29:17 +03:00 committed by GitHub
parent f8615e0ef0
commit c78f5a8225
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 500 additions and 296 deletions

View File

@ -1225,6 +1225,8 @@ namespace nd4j {
template<typename T> template<typename T>
FORCEINLINE T& t(const Nd4jLong i, const Nd4jLong j); FORCEINLINE T& t(const Nd4jLong i, const Nd4jLong j);
template<typename T>
FORCEINLINE T& t(const Nd4jLong i, const Nd4jLong j, const Nd4jLong k);
/** /**
* returns array element with given index * returns array element with given index
@ -1235,6 +1237,8 @@ namespace nd4j {
template<typename T> template<typename T>
FORCEINLINE T t(const Nd4jLong i, const Nd4jLong j) const; FORCEINLINE T t(const Nd4jLong i, const Nd4jLong j) const;
template<typename T>
FORCEINLINE T t(const Nd4jLong i, const Nd4jLong j, const Nd4jLong k) const;
/** /**
@ -2040,6 +2044,23 @@ T& NDArray::t(const Nd4jLong i, const Nd4jLong j) {
return *(reinterpret_cast<T*>(bufferWithOffset(offset))); return *(reinterpret_cast<T*>(bufferWithOffset(offset)));
} }
template <typename T>
T& NDArray::t(const Nd4jLong i, const Nd4jLong j, const Nd4jLong k) {
if (rankOf() != 3 || i >= sizeAt(0) || j >= sizeAt(1) || k >= sizeAt(2))
throw std::invalid_argument("NDArray::t(i,j,k): one of input indexes is out of array length or rank!=2 !");
if (DataTypeUtils::fromT<T>() != _dataType)
throw std::invalid_argument("NDArray::t(i,j,k): type of array is not equal to template type T!");
if(!isActualOnHostSide())
syncToHost();
Nd4jLong coords[3] = {i, j, k};
auto offset = shape::getOffset(0, shapeOf(), stridesOf(), coords, rankOf());
tickWriteHost();
return *(reinterpret_cast<T*>(bufferWithOffset(offset)));
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
template <typename T> template <typename T>
T NDArray::t(const Nd4jLong i) const { T NDArray::t(const Nd4jLong i) const {
@ -2074,6 +2095,23 @@ T NDArray::t(const Nd4jLong i, const Nd4jLong j) const {
return *(reinterpret_cast<T*>(bufferWithOffset(offset))); return *(reinterpret_cast<T*>(bufferWithOffset(offset)));
} }
template <typename T>
T NDArray::t(const Nd4jLong i, const Nd4jLong j, const Nd4jLong k) const {
if (rankOf() != 3 || i >= sizeAt(0) || j >= sizeAt(1) || k >= sizeAt(2))
throw std::invalid_argument("NDArray::t(i,j,k): one of input indexes is out of array length or rank!=2 !");
if (DataTypeUtils::fromT<T>() != _dataType)
throw std::invalid_argument("NDArray::t(i,j,k): type of array is not equal to template type T!");
if(!isActualOnHostSide())
syncToHost();
Nd4jLong coords[3] = {i, j, k};
auto offset = shape::getOffset(0, shapeOf(), stridesOf(), coords, rankOf());
tickReadHost();
return *(reinterpret_cast<T*>(bufferWithOffset(offset)));
}
#ifndef __JAVACPP_HACK__ #ifndef __JAVACPP_HACK__
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
std::shared_ptr<DataBuffer> NDArray::getDataBuffer() const { std::shared_ptr<DataBuffer> NDArray::getDataBuffer() const {

View File

@ -1101,9 +1101,9 @@ void NDArray::printBuffer(const char* msg, Nd4jLong limit, const bool sync) cons
printf("["); printf("[");
if (this->isR()) { if (this->isR()) {
for (Nd4jLong e = 0; e < limit; e++) { for (Nd4jLong e = 0; e < limit; e++) {
printf("%f", this->e<float>(e)); if (e)
if (e < limit - 1)
printf(", "); printf(", ");
printf("%f", this->e<float>(e));
} }
} }
else if (this->isZ()) { else if (this->isZ()) {

View File

@ -22,7 +22,7 @@
#include <dll.h> #include <dll.h>
#include <helpers/RandomLauncher.h> #include <helpers/RandomLauncher.h>
#include <graph/RandomGenerator.h> #include <graph/RandomGenerator.h>
#include <ops/declarable/CustomOperations.h> //#include <ops/declarable/CustomOperations.h>
#include <helpers/PointersManager.h> #include <helpers/PointersManager.h>
namespace nd4j { namespace nd4j {

View File

@ -189,7 +189,7 @@ namespace functions {
auto dx = static_cast<T*>(vdx); auto dx = static_cast<T*>(vdx);
auto extraParams = static_cast<T*>(vextraParams); auto extraParams = static_cast<T*>(vextraParams);
auto reductionBuffer = static_cast<T*>(vreductionBuffer); auto reductionBuffer = static_cast<T*>(vreductionBuffer);
auto order = shape::order(xShapeInfo);
int tid = blockIdx.x * blockDim.x + threadIdx.x; int tid = blockIdx.x * blockDim.x + threadIdx.x;
__shared__ volatile int resultScalar; __shared__ volatile int resultScalar;
@ -293,7 +293,7 @@ namespace functions {
auto n = shape::length(xShapeInfo); auto n = shape::length(xShapeInfo);
auto xElementWiseStride = shape::elementWiseStride(xShapeInfo); auto xElementWiseStride = shape::elementWiseStride(xShapeInfo);
if(xElementWiseStride >= 1) { if(xElementWiseStride >= 1 && order == 'c') {
for(Nd4jLong i = tid;i < n; i += (blockDim.x * gridDim.x)) { for(Nd4jLong i = tid;i < n; i += (blockDim.x * gridDim.x)) {
IndexValue <T> indexVal = {dx[i * xElementWiseStride], i}; IndexValue <T> indexVal = {dx[i * xElementWiseStride], i};
reduction = OpType::update(reduction, indexVal, extraParams); reduction = OpType::update(reduction, indexVal, extraParams);

View File

@ -52,91 +52,32 @@ namespace helpers {
for (Nd4jLong batch = 0; batch < batchCount; batch++) { for (Nd4jLong batch = 0; batch < batchCount; batch++) {
auto patch = listOfMatricies->at(batch); auto patch = listOfMatricies->at(batch);
auto outMatrix = listOfOutputs->at(batch); auto outMatrix = listOfOutputs->at(batch);
//auto patchBorder = patch->sizeAt(0);
if (theSame) { // SAME case
for (Nd4jLong i = 0; i < outRowDim; i++) {
for (Nd4jLong j = 0; j < outColDim; j++) {
Nd4jLong pos = 0;
//for (Nd4jLong k = 0; k < outputLastDim; k++) {
auto rowStart = i * strideRow - rowCast;
auto colStart = j * strideCol - colCast;
auto rowEnd = rowStart + sizeRow * rateRow;
auto colEnd = colStart + sizeCol * rateCol;
auto pixel = 0LL;
for (auto row = rowStart; row < rowEnd; row += rateRow)
for (auto col = colStart; col < colEnd; col += rateCol)
for (auto pixel = 0; pixel < lastDim; pixel++) {
if (row >=0 && col >= 0 && row < rowDim && col < colDim)
outMatrix->p<T>(i, j, pos, patch->e<T>(row, col, pixel));
pos++;
}
//}
}
}
} else { // VALID case for (Nd4jLong i = 0; i < outRowDim; i++) {
for (Nd4jLong i = 0; i < outRowDim; i++) { for (Nd4jLong j = 0; j < outColDim; j++) {
for (Nd4jLong j = 0; j < outColDim; j++) { Nd4jLong pos = 0;
Nd4jLong pos = 0; //for (Nd4jLong k = 0; k < outputLastDim; k++) {
//for (Nd4jLong k = 0; k < outputLastDim; k++) { auto rowStart = i * strideRow - (theSame?rowCast:0);
auto rowStart = i * strideRow; auto colStart = j * strideCol - (theSame?colCast:0);
auto colStart = j * strideCol; auto rowEnd = rowStart + sizeRow * rateRow;
auto rowEnd = math::nd4j_min(rowStart + sizeRow * rateRow, rowDim); auto colEnd = colStart + sizeCol * rateCol;
auto colEnd = math::nd4j_min(colStart + sizeCol * rateCol, colDim); if (!theSame) {
auto pixel = 0LL; rowEnd = math::nd4j_min(rowStart + sizeRow * rateRow, rowDim);
for (auto row = rowStart; row < rowEnd; row += rateRow) colEnd = math::nd4j_min(colStart + sizeCol * rateCol, colDim);
for (auto col = colStart; col < colEnd; col += rateCol)
for (auto pixel = 0; pixel < lastDim; pixel++)
outMatrix->p<T>(i,j,pos++, patch->e<T>(row, col, pixel));
//}
} }
//auto pixel = 0LL;
for (auto row = rowStart; row < rowEnd; row += rateRow)
for (auto col = colStart; col < colEnd; col += rateCol)
for (auto pixel = 0; pixel < lastDim; pixel++) {
bool setUp = (theSame && row >= 0 && col >= 0 && row < rowDim && col < colDim) || (!theSame);
if (setUp) {
outMatrix->t<T>(i, j, pos) = patch->e<T>(row, col, pixel);
}
pos++;
}
} }
} }
} }
////#pragma omp parallel for
// for (Nd4jLong e = 0; e < batchCount; ++e) {
// auto patch = listOfMatricies->at(e);
// auto outMatrix = listOfOutputs->at(e);
// auto patchBorder = patch->sizeAt(0);
// //int startRow = 0;
// //int startCol = 0;
// Nd4jLong pos = 0;
// for (int i = 0; i < rowDim; i += stradeRow)
// for (int j = 0; j < colDim; j += stradeCol)
// for (int l = 0; l < ksizeRowsEffective; l++)
// for (int m = 0; m < ksizeColsEffective; m++) {
// //for (Nd4jLong pos = 0; pos < outputLastDim; pos++)
// for (Nd4jLong k = 0; k < lastDim; ++k) {
// if (theSame) {
// if (j + m * rateCol < colDim &&
// i + l * rateRow < rowDim)
// outMatrix->p<T>(i, j, pos++, patch->e<T>(i + rateRow * l, j + m * rateCol, k));
//// pos ++; //= ksize;
// if (pos >= outLastDim) {
// pos = 0;
// //break;
// }
// }
// else {
//// if (l + i < rowDim && m + j < colDim && i + rateRow * l < patchBorder) // && i + rateRow * l < sizeRow && j + m * rateCol < sizeCol
//// outMatrix->p<T>(i, j, pos, patch->e<T>(i + rateRow * l, j + m * rateCol, k));
// if (j + m * rateCol < colDim &&
// i + l * rateRow < rowDim) // && i + rateRow * l < sizeRow && j + m * rateCol < sizeCol
// outMatrix->p<T>(pos++, patch->e<T>(i + rateRow * l, j + m * rateCol, k));
// //pos++;
//// if (pos >= outLastDim)
//// pos = 0;
// if (pos >= outMatrix->lengthOf()) { // stop looping and try next batch
// k = lastDim;
// m = sizeCol;
// l = sizeRow;
// j = colDim;
// i = rowDim;
// }
// }
// }
// }
// }
} }

View File

@ -987,8 +987,9 @@ BUILD_SINGLE_TEMPLATE(template void clipByNorm_, (NDArray& input, NDArray& outpu
template <typename T> template <typename T>
static void clipByGlobalNorm_(std::vector<NDArray*> const& inputs, double clipNorm, nd4j::memory::Workspace* workspace, std::vector<NDArray*>& outputs, bool isInplace) { static void clipByGlobalNorm_(std::vector<NDArray*> const& inputs, double clipNorm, nd4j::memory::Workspace* workspace, std::vector<NDArray*>& outputs, bool isInplace) {
NDArray globalNorm = NDArrayFactory::create<T>(0, inputs[0]->getContext()); //sqrt(sum([l2norm(t)**2 for t in t_list])) NDArray globalNorm = NDArrayFactory::create<T>(0, inputs[0]->getContext()); //sqrt(sum([l2norm(t)**2 for t in t_list]))
PRAGMA_OMP_PARALLEL_FOR
for (auto input: inputs) { for (size_t i = 0; i < inputs.size(); i++) {
auto input = inputs[i];
auto l2norm = input->reduceNumber(reduce::Norm2); auto l2norm = input->reduceNumber(reduce::Norm2);
globalNorm += l2norm * l2norm; globalNorm += l2norm * l2norm;
} }
@ -998,6 +999,7 @@ BUILD_SINGLE_TEMPLATE(template void clipByNorm_, (NDArray& input, NDArray& outpu
const T factor = clipNorm / globalNorm.e<T>(0); const T factor = clipNorm / globalNorm.e<T>(0);
PRAGMA_OMP_PARALLEL_FOR
for (size_t e = 0; e < inputs.size(); e++) { for (size_t e = 0; e < inputs.size(); e++) {
// all-reduce // all-reduce
auto input = inputs[e]; auto input = inputs[e];

View File

@ -565,7 +565,9 @@ void softmaxDerivative(nd4j::LaunchContext * context, const NDArray& input, NDAr
template <typename T> template <typename T>
linkage void thresholdReluDerivative_(NDArray* input, double theta, NDArray* dLdO, NDArray* output) { linkage void thresholdReluDerivative_(NDArray* input, double theta, NDArray* dLdO, NDArray* output) {
auto derivative = LAMBDA_TT(_x, grO, theta) {if (_x > theta) return grO; else return static_cast<T>(0); };
input->applyPairwiseLambda(dLdO, derivative, output);
} }
void thresholdReluDerivative(nd4j::LaunchContext * context, NDArray* input, double threshold, NDArray* dLdO, NDArray* output) { void thresholdReluDerivative(nd4j::LaunchContext * context, NDArray* input, double threshold, NDArray* dLdO, NDArray* output) {

View File

@ -29,73 +29,162 @@ namespace nd4j {
namespace ops { namespace ops {
namespace helpers { namespace helpers {
// template <typename T>
// static __global__ void globalExtractPatchesKernel(bool theSame, int batchCount, int sizeRow, int sizeCol, int rowDim, int colDim, int outRowDim, int outColDim, int strideRow, int strideCol, int rateRow, int rateCol, int rowCast, int colCast, int lastDim, T* input, Nd4jLong* patchShape, Nd4jLong* inputOffsets, T* output, Nd4jLong* outTadShape, Nd4jLong* outputOffsets) {
// //globalExtractPatches_(void *vinput, Nd4jLong *xTadShape, Nd4jLong *xTadOffsets, void *voutput, Nd4jLong *zTadShape, Nd4jLong *zTadOffsets, const int numTads, const int sizeRow, const int sizeCol, const int stradeRow, const int stradeCol, const int rateRow, const int rateCol, const bool theSame, const int lastDim, const int rowDim, const int colDim) {
// const int warpSize = lastDim;
// const int tid = blockIdx.x * gridDim.x + threadIdx.x;
// const int warpIdx = tid / warpSize;
// const int warpPos = tid % warpSize;
// const int numWarps = 1; //(gridDim.x * blockDim.x) / warpSize;
// const int patchLength = shape::length(outTadShape);
//
// auto xShape = shape::shapeOf(patchShape);
// auto xStride = shape::stride(patchShape);
// auto xRank = shape::rank(patchShape);
//
// for (int e = 0; e < batchCount; e += numWarps) {
// auto patch = input + inputOffsets[e];
// auto matrix = output + outputOffsets[e];
// int iter = 0;
//
// for (Nd4jLong i = 0; i < outRowDim; i++) {
// for (Nd4jLong j = 0; j < outColDim; j++) {
// Nd4jLong pos = 0;
// //for (Nd4jLong k = 0; k < outputLastDim; k++) {
// auto rowStart = i * strideRow - (theSame?rowCast:0);
// auto colStart = j * strideCol - (theSame?colCast:0);
// auto rowEnd = rowStart + sizeRow * rateRow;
// auto colEnd = colStart + sizeCol * rateCol;
// if (!theSame) {
// rowEnd = math::nd4j_min(int(rowStart + sizeRow * rateRow), rowDim);
// colEnd = math::nd4j_min(int(colStart + sizeCol * rateCol), colDim);
// }
// //auto pixel = 0LL;
// for (auto row = rowStart; row < rowEnd; row += rateRow)
// for (auto col = colStart; col < colEnd; col += rateCol)
// for (auto pixel = 0; pixel < lastDim; pixel++) {
// Nd4jLong zPos[] = {i, j, pos};
// Nd4jLong xPos[] = {row, col, pixel};
// auto zIndex = shape::getOffset(0, shape::shapeOf(outTadShape), shape::stride(outTadShape), zPos, 3);
// auto xIndex = shape::getOffset(0, shape::shapeOf(patchShape), shape::stride(patchShape), xPos, 3);
// if (theSame) { // SAME case
// if (row >= 0 && col >= 0 && row < rowDim && col < colDim)
// matrix[zIndex] = patch[xIndex]; //outMatrix->p<T>(i, j, pos, patch->e<T>(row, col, pixel));
// //pos++;
// }
// else { // VALID case
// matrix[zIndex] = patch[xIndex]; //outMatrix->p<T>(i, j, pos++, patch->e<T>(row, col, pixel));
// }
// pos++;
// }
// }
// }
// __syncthreads();
// }
// }
template <typename T> template <typename T>
static __global__ void globalExtractPatches_(void *vinput, Nd4jLong *xTadShape, Nd4jLong *xTadOffsets, void *voutput, Nd4jLong *zTadShape, Nd4jLong *zTadOffsets, const int numTads, const int sizeRow, const int sizeCol, const int stradeRow, const int stradeCol, const int rateRow, const int rateCol, const bool theSame, const int lastDim, const int rowDim, const int colDim) { static __global__ void globalExtractPatchesKernel(bool theSame, int batchCount, int sizeRow, int sizeCol, int rowDim, int colDim, int outRowDim, int outColDim, int strideRow, int strideCol, int rateRow, int rateCol, int rowCast, int colCast, int lastDim, T* input, Nd4jLong* patchShape, Nd4jLong* inputOffsets, T* output, Nd4jLong* outTadShape, Nd4jLong* outputOffsets) {
auto input = reinterpret_cast<T*>(vinput); __shared__ Nd4jLong* xShapeOf;
auto output = reinterpret_cast<T*>(voutput); __shared__ Nd4jLong* xStrideOf;
__shared__ Nd4jLong* zShapeOf;
__shared__ Nd4jLong* zStrideOf;
const int warpSize = lastDim; if (0 == threadIdx.x) {
const int tid = blockIdx.x * gridDim.x + threadIdx.x; xShapeOf = shape::shapeOf(patchShape);
const int warpIdx = tid / warpSize; xStrideOf = shape::stride(patchShape);
const int warpPos = tid % warpSize; zShapeOf = shape::shapeOf(outTadShape);
const int numWarps = (gridDim.x * blockDim.x) / warpSize; zStrideOf = shape::stride(outTadShape);
const int patchLength = shape::length(zTadShape);
auto xShape = shape::shapeOf(xTadShape);
auto xStride = shape::stride(xTadShape);
auto xRank = shape::rank(xTadShape);
for (int e = warpIdx; e < numTads; e += numWarps) {
auto patch = input + xTadOffsets[e];
auto matrix = output + zTadOffsets[e];
int iter = 0;
for (int i = 0; i < rowDim; i += stradeRow)
for (int j = 0; j < colDim; j += stradeCol)
for (int l = 0; l < sizeRow && l + i < rowDim; l++)
for (int m = 0; m < sizeCol && m + j < colDim; m++) {
auto pos = warpPos + (iter * lastDim);
if (pos < patchLength) {
auto x = i + rateRow * l;
auto y = j + m * rateCol;
Nd4jLong xIndex[3] = {x, y, warpPos};
matrix[shape::getIndexOffset(pos, zTadShape, patchLength)] = patch[shape::getOffset(0, xShape, xStride, xIndex, xRank)];
} else {
// early loop termination
i = rowDim;
j = colDim;
l = sizeRow;
m = sizeCol;
}
iter++;
}
__syncthreads();
} }
__syncthreads();
auto start = threadIdx.x + blockIdx.x * blockDim.x;
auto step = blockDim.x * gridDim.x;
for (Nd4jLong batch = start; batch < batchCount; batch += step) {
auto patch = input + inputOffsets[batch];// listOfMatricies->at(batch);
auto outMatrix = output + outputOffsets[batch]; //listOfOutputs->at(batch);
for (Nd4jLong i = 0; i < outRowDim; i++) {
for (Nd4jLong j = 0; j < outColDim; j++) {
Nd4jLong pos = 0;
//for (Nd4jLong k = 0; k < outputLastDim; k++) {
auto rowStart = i * strideRow - (theSame?rowCast:0);
auto colStart = j * strideCol - (theSame?colCast:0);
auto rowEnd = rowStart + sizeRow * rateRow;
auto colEnd = colStart + sizeCol * rateCol;
if (!theSame) {
rowEnd = math::nd4j_min(rowStart + sizeRow * rateRow, Nd4jLong (rowDim));
colEnd = math::nd4j_min(colStart + sizeCol * rateCol, Nd4jLong (colDim));
}
//auto pixel = 0LL;
for (auto row = rowStart; row < rowEnd; row += rateRow)
for (auto col = colStart; col < colEnd; col += rateCol)
for (auto pixel = 0; pixel < lastDim; pixel++) {
Nd4jLong zPos[] = {i, j, pos};
Nd4jLong xPos[] = {row, col, pixel};
bool setUp = (theSame && row >= 0 && col >= 0 && row < rowDim && col < colDim) || (!theSame);
if (setUp) { // VALID or SAME cases
outMatrix[shape::getOffset(0, zShapeOf, zStrideOf, zPos, 3)] = patch[shape::getOffset(0, xShapeOf, xStrideOf, xPos, 3)];
}
pos++;
}
}
}
}
} }
template <typename T> template <typename T>
static void _extractPatches(nd4j::LaunchContext * context, NDArray* images, NDArray* output, int sizeRow, int sizeCol, int stradeRow, int stradeCol, int rateRow, int rateCol, bool theSame){ static void _extractPatches(nd4j::LaunchContext * context, NDArray* images, NDArray* output, int sizeRow, int sizeCol, int strideRow, int strideCol, int rateRow, int rateCol, bool theSame){
std::array<int, 3> restDims = {1, 2, 3}; NDArray::prepareSpecialUse({output}, {images});
std::vector<int> restDims({1, 2, 3}); // the first and the last dims
// 3D matricies - 2D matricies of vectors (if last dim is greater than 1)
//int e = 0;
const int ksizeRowsEffective = sizeRow + (sizeRow - 1) * (rateRow - 1);
const int ksizeColsEffective = sizeCol + (sizeCol - 1) * (rateCol - 1);
const int ksize = ksizeRowsEffective * ksizeColsEffective;
Nd4jLong lastDim = images->sizeAt(3);
Nd4jLong outLastDim = output->sizeAt(3);
Nd4jLong rowDim = images->sizeAt(1);
Nd4jLong colDim = images->sizeAt(2);
Nd4jLong outRowDim = output->sizeAt(1);
Nd4jLong outColDim = output->sizeAt(2);
auto rowCast = 1; //(sizeRow - 1)*rateRow < outRowDim/sizeRow ?0:1;///(ksize * lastDim > rowDim * ksizeColsEffective + lastDim?1:0);
auto colCast = 1; //colDim / ksizeColsEffective +2 <= sizeCol?0:1;//(ksize * lastDim > ksizeRowsEffective * colDim + lastDim?1:0);
if (sizeRow * rateRow < 3)
rowCast = 0;
if (sizeCol * rateCol < 3)
colCast = 0;
//images->tickReadDevice();
//if (images->isActualOnDeviceSide())
//images->syncToDevice();
auto packX = nd4j::ConstantTadHelper::getInstance()->tadForDimensions(images->getShapeInfo(), restDims.data(), restDims.size()); auto packX = nd4j::ConstantTadHelper::getInstance()->tadForDimensions(images->getShapeInfo(), restDims.data(), restDims.size());
auto packZ = nd4j::ConstantTadHelper::getInstance()->tadForDimensions(output->getShapeInfo(), restDims.data(), restDims.size()); auto packZ = nd4j::ConstantTadHelper::getInstance()->tadForDimensions(output->getShapeInfo(), restDims.data(), restDims.size());
int batchCount = packX.numberOfTads(); //'listOfMatricies->size(); //lengthOf() / ksize;
//printf("Batch Count is %d\n", batchCount);
//shape::printShapeInfo(packX.primaryShapeInfo());
//NDArray::prepareSpecialUse({output}, {images});
PointersManager manager(context, "helpers::extractPatches"); PointersManager manager(context, "helpers::extractPatches");
int lastDim = images->sizeAt(3); auto stream = context->getCudaStream();
int rowDim = images->sizeAt(1); auto imagesBuffer = reinterpret_cast<T*>(images->specialBuffer());
int colDim = images->sizeAt(2); auto outputBuffer = reinterpret_cast<T*>(output->specialBuffer());
//images->printIndexedBuffer("INPUT");
globalExtractPatches_<T><<<512, 512, 1024, *context->getCudaStream()>>>(images->getSpecialBuffer(), packX.specialShapeInfo(), packX.specialOffsets(), output->getSpecialBuffer(), packZ.specialShapeInfo(), packZ.specialOffsets(), packX.numberOfTads(), sizeRow, sizeCol, stradeRow, stradeCol, rateRow, rateCol, theSame, lastDim, rowDim, colDim); // globalExtractPatchesKernel<T><<<512, 512, 1024, *context->getCudaStream()>>>(theSame, batchCount, sizeRow, sizeCol,
globalExtractPatchesKernel<T><<<128, 128, 1024, *stream>>>(theSame, batchCount, sizeRow, sizeCol,
output->tickWriteDevice(); rowDim, colDim, outRowDim, outColDim, strideRow, strideCol, rateRow, rateCol, rowCast, colCast, lastDim,
imagesBuffer, packX.specialShapeInfo(), packX.specialOffsets(), outputBuffer, packZ.specialShapeInfo(),
packZ.specialOffsets());
//extractPatchesKernel<T><<<batchCount, 512, 1024, *stream>>>(theSame, batchCount, sizeRow, sizeCol, rowDim, colDim, outRowDim, outColDim, stradeRow, stradeCol, rateRow, rateCol, rowCast, colCast, lastDim, imagesBuffer, packX.specialShapeInfo(), packX.platformOffsets(), outputBuffer, packZ.specialShapeInfo(), packZ.platformOffsets());
//output->tickWriteDevice();
//output->printIndexedBuffer("OUTPUT");
manager.synchronize(); manager.synchronize();
NDArray::registerSpecialUse({output}, {images});
} }
BUILD_SINGLE_TEMPLATE(template void _extractPatches, (nd4j::LaunchContext * context, NDArray* input, NDArray* output, int sizeRow, int sizeCol, int stradeRow, int stradeCol, int rateRow, int rateCol, bool theSame), LIBND4J_TYPES); BUILD_SINGLE_TEMPLATE(template void _extractPatches, (nd4j::LaunchContext * context, NDArray* input, NDArray* output, int sizeRow, int sizeCol, int stradeRow, int stradeCol, int rateRow, int rateCol, bool theSame), LIBND4J_TYPES);
@ -106,6 +195,76 @@ namespace helpers {
BUILD_SINGLE_SELECTOR(xType, _extractPatches, (context, images, output, sizeRow, sizeCol, stradeRow, stradeCol, rateRow, rateCol, theSame), LIBND4J_TYPES); BUILD_SINGLE_SELECTOR(xType, _extractPatches, (context, images, output, sizeRow, sizeCol, stradeRow, stradeCol, rateRow, rateCol, theSame), LIBND4J_TYPES);
} }
// std::vector<int> restDims({1, 2, 3}); // the first and the last dims
// std::unique_ptr<ResultSet> listOfMatricies(images->allTensorsAlongDimension(restDims));
// std::unique_ptr<ResultSet> listOfOutputs(output->allTensorsAlongDimension(restDims));
// // 3D matricies - 2D matricies of vectors (if last dim is greater than 1)
// //int e = 0;
// const int ksizeRowsEffective = sizeRow + (sizeRow - 1) * (rateRow - 1);
// const int ksizeColsEffective = sizeCol + (sizeCol - 1) * (rateCol - 1);
// const int ksize = ksizeRowsEffective * ksizeColsEffective;
// int batchCount = listOfMatricies->size(); //lengthOf() / ksize;
// Nd4jLong lastDim = images->sizeAt(3);
// Nd4jLong outLastDim = output->sizeAt(3);
// Nd4jLong rowDim = images->sizeAt(1);
// Nd4jLong colDim = images->sizeAt(2);
// Nd4jLong outRowDim = output->sizeAt(1);
// Nd4jLong outColDim = output->sizeAt(2);
// auto rowCast = 1; //(sizeRow - 1)*rateRow < outRowDim/sizeRow ?0:1;///(ksize * lastDim > rowDim * ksizeColsEffective + lastDim?1:0);
// auto colCast = 1; //colDim / ksizeColsEffective +2 <= sizeCol?0:1;//(ksize * lastDim > ksizeRowsEffective * colDim + lastDim?1:0);
// if (sizeRow * rateRow < 3)
// rowCast = 0;
// if (sizeCol * rateCol < 3)
// colCast = 0;
// //Nd4jLong outputLastDim = output->sizeAt(3);
// PRAGMA_OMP_PARALLEL_FOR
// for (Nd4jLong batch = 0; batch < batchCount; batch++) {
// auto patch = listOfMatricies->at(batch);
// auto outMatrix = listOfOutputs->at(batch);
// //auto patchBorder = patch->sizeAt(0);
// if (theSame) { // SAME case
// for (Nd4jLong i = 0; i < outRowDim; i++) {
// for (Nd4jLong j = 0; j < outColDim; j++) {
// Nd4jLong pos = 0;
// //for (Nd4jLong k = 0; k < outputLastDim; k++) {
// auto rowStart = i * strideRow - rowCast;
// auto colStart = j * strideCol - colCast;
// auto rowEnd = rowStart + sizeRow * rateRow;
// auto colEnd = colStart + sizeCol * rateCol;
// auto pixel = 0LL;
// for (auto row = rowStart; row < rowEnd; row += rateRow)
// for (auto col = colStart; col < colEnd; col += rateCol)
// for (auto pixel = 0; pixel < lastDim; pixel++) {
// if (row >=0 && col >= 0 && row < rowDim && col < colDim)
// outMatrix->p<T>(i, j, pos, patch->e<T>(row, col, pixel));
// pos++;
// }
// //}
// }
// }
//
// } else { // VALID case
// for (Nd4jLong i = 0; i < outRowDim; i++) {
// for (Nd4jLong j = 0; j < outColDim; j++) {
// Nd4jLong pos = 0;
// //for (Nd4jLong k = 0; k < outputLastDim; k++) {
// auto rowStart = i * strideRow;
// auto colStart = j * strideCol;
// auto rowEnd = math::nd4j_min(rowStart + sizeRow * rateRow, rowDim);
// auto colEnd = math::nd4j_min(colStart + sizeCol * rateCol, colDim);
// auto pixel = 0LL;
// for (auto row = rowStart; row < rowEnd; row += rateRow)
// for (auto col = colStart; col < colEnd; col += rateCol)
// for (auto pixel = 0; pixel < lastDim; pixel++)
// outMatrix->p<T>(i,j,pos++, patch->e<T>(row, col, pixel));
// //}
// }
// }
// }
// }
//
//
//
} }
} }
} }

View File

@ -1408,7 +1408,35 @@ void eye(nd4j::LaunchContext * context, NDArray& output) {
template <typename T> template <typename T>
static void clipByGlobalNorm_(nd4j::LaunchContext * context, std::vector<NDArray*> const& inputs, double clipNorm, nd4j::memory::Workspace* workspace, std::vector<NDArray*>& outputs, bool isInplace) { static void clipByGlobalNorm_(nd4j::LaunchContext * context, std::vector<NDArray*> const& inputs, double clipNorm, nd4j::memory::Workspace* workspace, std::vector<NDArray*>& outputs, bool isInplace) {
NDArray globalNorm = NDArrayFactory::create<T>(0, inputs[0]->getContext()); //sqrt(sum([l2norm(t)**2 for t in t_list]))
PRAGMA_OMP_PARALLEL_FOR
for (auto i = 0; i < inputs.size(); i++) {
auto input = inputs[i];
auto l2norm = input->reduceNumber(reduce::Norm2);
globalNorm += l2norm * l2norm;
}
globalNorm.applyTransform(transform::Sqrt, nullptr, nullptr);// = nd4j::math::nd4j_sqrt(globalNorm);
outputs[inputs.size()]->p(0, globalNorm);
globalNorm.syncToHost();
const T factor = clipNorm / globalNorm.e<T>(0);
PRAGMA_OMP_PARALLEL_FOR
for (size_t e = 0; e < inputs.size(); e++) {
// all-reduce
auto input = inputs[e];
auto output = outputs[e];
if (globalNorm.e<double>(0) <= clipNorm) {
output->assign(input);
}
else {
auto lambda = LAMBDA_T(_x, factor) { return _x * factor; };
input->applyLambda(lambda, output);
}
}
} }
void clipByGlobalNorm(nd4j::LaunchContext * context, std::vector<NDArray*> const& inputs, double clipNorm, nd4j::memory::Workspace* workspace, std::vector<NDArray*>& outputs, bool isInplace) { void clipByGlobalNorm(nd4j::LaunchContext * context, std::vector<NDArray*> const& inputs, double clipNorm, nd4j::memory::Workspace* workspace, std::vector<NDArray*>& outputs, bool isInplace) {

View File

@ -781,14 +781,32 @@ inline __device__ double nd4j_atomicMin<double>(double* address, double val) {
} }
template <> template <>
inline __device__ uint64_t nd4j_atomicMin<uint64_t>(uint64_t* address, uint64_t val) { inline __device__ uint64_t nd4j_atomicMin<uint64_t>(uint64_t* address, uint64_t val) {
#if __CUDA_ARCH__ >= 350
return atomicMin((unsigned long long*)address, (unsigned long long)val); return atomicMin((unsigned long long*)address, (unsigned long long)val);
#else
unsigned long long int* address_as_ull = (unsigned long long int*)address;
unsigned long long int old = __double_as_longlong(val), assumed;
do {
assumed = old;
old = atomicCAS(address_as_ull, assumed, math::nd4j_min((unsigned long long)val, assumed));
} while (assumed != old);
return old;
#endif
} }
template <> template <>
inline __device__ Nd4jLong nd4j_atomicMin<Nd4jLong>(Nd4jLong* address, Nd4jLong val) { inline __device__ Nd4jLong nd4j_atomicMin<Nd4jLong>(Nd4jLong* address, Nd4jLong val) {
return (Nd4jLong)atomicMin((unsigned long long*)address, (unsigned long long)val); #if __CUDA_ARCH__ >= 350
// else return atomicMin((unsigned long long*)address, (unsigned long long)val);
// return (Nd4jLong)atomicMax((unsigned long long*)address, (unsigned long long)val); #else
unsigned long long int* address_as_ull = (unsigned long long int*)address;
unsigned long long int old = (unsigned long long)val, assumed;
do {
assumed = old;
old = atomicCAS(address_as_ull, assumed, math::nd4j_min(val, (Nd4jLong)assumed));
} while (assumed != old);
return old;
#endif
} }
template <> template <>
@ -952,7 +970,17 @@ inline __device__ bfloat16 nd4j_atomicMax<bfloat16>(bfloat16* address, bfloat16
template <> template <>
inline __device__ uint64_t nd4j_atomicMax<uint64_t>(uint64_t* address, uint64_t val) { inline __device__ uint64_t nd4j_atomicMax<uint64_t>(uint64_t* address, uint64_t val) {
return atomicMax((unsigned long long*)address, (unsigned long long)val); #if __CUDA_ARCH__ >= 350
return atomicMax((unsigned long long*)address, (unsigned long long)val);
#else
unsigned long long int* address_as_ull = (unsigned long long int*)address;
unsigned long long int old = __double_as_longlong(val), assumed;
do {
assumed = old;
old = atomicCAS(address_as_ull, assumed, math::nd4j_max((unsigned long long)val, assumed));
} while (assumed != old);
return old;
#endif
} }
template <> template <>

View File

@ -28,8 +28,13 @@
#include <specials_cuda.h> #include <specials_cuda.h>
#include <TAD.h> #include <TAD.h>
#include <MmulHelper.h> #include <MmulHelper.h>
#include <helpers/PointersManager.h>
#include <cuda.h> #include <cuda.h>
#include <helpers/RandomLauncher.h>
#include <ConstantShapeHelper.h>
#include <ConstantTadHelper.h>
#include <ShapeDescriptor.h>
#include <array/ConstantDataBuffer.h>
using namespace nd4j; using namespace nd4j;
using namespace nd4j::graph; using namespace nd4j::graph;
@ -2532,54 +2537,28 @@ TEST_F(CudaBasicsTests1, execReduce3TAD_1) {
NDArray z('c', {3}, {100,100,100}, nd4j::DataType::DOUBLE); NDArray z('c', {3}, {100,100,100}, nd4j::DataType::DOUBLE);
std::vector<int> dimensions = {0,1}; std::vector<int> dimensions = {0,1};
auto packX = ConstantTadHelper::getInstance()->tadForDimensions(x.shapeInfo(), dimensions);
// evaluate xTad data LaunchContext* context = x.getContext();
shape::TAD xTad;
xTad.init(x.getShapeInfo(), dimensions.data(), dimensions.size());
xTad.createTadOnlyShapeInfo();
xTad.createOffsets();
// prepare input arrays for prepareDataForCuda function
std::vector<std::pair<void*,size_t>> hostData;
hostData.emplace_back(dimensions.data(), dimensions.size() * sizeof(int)); // 0 -- dimensions
hostData.emplace_back(xTad.tadOnlyShapeInfo, shape::shapeInfoByteLength(xTad.tadOnlyShapeInfo));// 1 -- xTadShapeInfo
hostData.emplace_back(xTad.tadOffsets, xTad.numTads * sizeof(Nd4jLong)); // 2 -- xTadOffsets
std::vector<void*> devicePtrs(hostData.size(), nullptr);
// create cuda stream and LaunchContext
cudaError_t cudaResult;
cudaStream_t stream;
cudaResult = cudaStreamCreate(&stream); ASSERT_EQ(0, cudaResult);
LaunchContext lc(&stream);
// allocate required amount of global device memory and copy host data to it
cudaResult = allocateDeviceMem(lc, devicePtrs, hostData); ASSERT_EQ(0, cudaResult);
x.syncToDevice(); x.syncToDevice();
y.syncToDevice(); y.syncToDevice();
PointersManager pm(context, "execReduce3TAD_1");
// call cuda kernel which calculates result // call cuda kernel which calculates result
NativeOpExecutioner::execReduce3TAD(&lc, nd4j::reduce3::Dot, NativeOpExecutioner::execReduce3TAD(context, nd4j::reduce3::Dot,
nullptr, x.getShapeInfo(), x.specialBuffer(), x.specialShapeInfo(), nullptr, x.getShapeInfo(), x.specialBuffer(), x.specialShapeInfo(),
nullptr, nullptr,
nullptr, y.getShapeInfo(), y.specialBuffer(), y.specialShapeInfo(), nullptr, y.getShapeInfo(), y.specialBuffer(), y.specialShapeInfo(),
nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(), nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
(int*)devicePtrs[0], dimensions.size(), nullptr, dimensions.size(),
(Nd4jLong*)devicePtrs[1], (Nd4jLong*)devicePtrs[2], (Nd4jLong*)devicePtrs[1], (Nd4jLong*)devicePtrs[2]); packX.specialShapeInfo(), packX.specialOffsets(), nullptr, nullptr);
pm.synchronize();
cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult); // cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult);
z.tickWriteDevice(); z.tickWriteDevice();
// z.printIndexedBuffer("OutputReduce3TAD");
// verify results // verify results
for (int e = 0; e < z.lengthOf(); e++) for (int e = 0; e < z.lengthOf(); e++)
ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5); ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5);
// free allocated global device memory
for(int i = 0; i < devicePtrs.size(); ++i) cudaFree(devicePtrs[i]);
// delete cuda stream
cudaResult = cudaStreamDestroy(stream); ASSERT_EQ(0, cudaResult);
} }
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -2622,7 +2601,7 @@ TEST_F(CudaBasicsTests1, execReduce3TAD_2) {
nullptr, y.getShapeInfo(), y.specialBuffer(), y.specialShapeInfo(), nullptr, y.getShapeInfo(), y.specialBuffer(), y.specialShapeInfo(),
nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(), nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
(int*)devicePtrs[0], dimensions.size(), (int*)devicePtrs[0], dimensions.size(),
(Nd4jLong*)devicePtrs[1], (Nd4jLong*)devicePtrs[2], (Nd4jLong*)devicePtrs[1], (Nd4jLong*)devicePtrs[2]); (Nd4jLong*)devicePtrs[1], (Nd4jLong*)devicePtrs[2], nullptr, nullptr);
cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult); cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult);
z.tickWriteDevice(); z.tickWriteDevice();
@ -2928,46 +2907,55 @@ TEST_F(CudaBasicsTests1, execSummaryStatsScalar_1) {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
TEST_F(CudaBasicsTests1, execRandom_1) { TEST_F(CudaBasicsTests1, execRandom_1) {
NDArray z('c', {10}, {100,0,0,0,0,0,0,0,0,0}, nd4j::DataType::DOUBLE); // NDArray z('c', {10}, {100,0,0,0,0,0,0,0,0,0}, nd4j::DataType::DOUBLE);
NDArray exp('c', {10}, {0.050942, -0.183229, -0.093921, 0.075469, 0.257166, -0.254838, 0.342227, -0.682188, -0.004345, 0.464633}, nd4j::DataType::DOUBLE); NDArray z('c', {10}, {100,0,0,0,0,0,0,0,0,100}, nd4j::DataType::FLOAT32);
NDArray exp('c', {10}, {0.050942, -0.183229, -0.093921, 0.075469, 0.257166, -0.254838, 0.342227, -0.682188, -0.004345, 0.464633}, nd4j::DataType::FLOAT32);
std::vector<double> extraArguments = {0., 0.5};
nd4j::graph::RandomGenerator gen(119,5); nd4j::graph::RandomGenerator gen(119,5);
// prepare input arrays for prepareDataForCuda function
std::vector<std::pair<void*,size_t>> hostData;
hostData.emplace_back(extraArguments.data(), extraArguments.size() * sizeof(double)); // 0 -- dimensions
std::vector<void*> devicePtrs(hostData.size(), nullptr);
// create cuda stream and LaunchContext
cudaError_t cudaResult; cudaError_t cudaResult;
cudaStream_t stream; NDArray* array = &z;
cudaResult = cudaStreamCreate(&stream); ASSERT_EQ(0, cudaResult); ExtraArguments arguments({0.f, 0.5f});
LaunchContext lc(&stream); auto context = z.getContext();
PointersManager pm(context, "tests::execRandom_1");
// allocate required amount of global device memory and copy host data to it // z.printIndexedBuffer("Input data");
cudaResult = allocateDeviceMem(lc, devicePtrs, hostData); ASSERT_EQ(0, cudaResult); // z.syncToDevice();
NativeOpExecutioner::execRandom(context, random::GaussianDistribution, &gen, array->buffer(), array->shapeInfo(), array->specialBuffer(), array->specialShapeInfo(), array->buffer(), array->shapeInfo(), array->specialBuffer(), array->specialShapeInfo(), array->buffer(), array->shapeInfo(), array->specialBuffer(), array->specialShapeInfo(), arguments.argumentsAsT(array->dataType()));
// call cuda kernel which calculates result pm.synchronize();
NativeOpExecutioner::execRandom(&lc, nd4j::random::GaussianDistribution,
&gen,
nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
devicePtrs[0]);
cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult);
z.tickWriteDevice(); z.tickWriteDevice();
// z.printIndexedBuffer("Output Gaussian");
// RandomLauncher::fillGaussian(context, gen, &z, 0.f, 0.5f);
// pm.synchronize();
// z.tickWriteDevice();
// z.printIndexedBuffer("Output Gaussian");
// verify results // cudaStream_t stream;
for (int e = 0; e < z.lengthOf(); e++) // cudaResult = cudaStreamCreate(&stream); ASSERT_EQ(0, cudaResult);
ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5); // LaunchContext lc(&stream);
//
// // ::execRandom(extraPointers, random::GaussianDistribution, &gen, z.buffer(), z.shapeInfo(), z.specialBuffer(), z.specialShapeInfo(), &extra);
// // call cuda kernel which calculates result
// NativeOpExecutioner::execRandom(&lc, nd4j::random::GaussianDistribution,
// &gen,
// nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
// nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
// nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
// extraArguments.argumentsAsT(z.dataType()));
//
// cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult);
// ASSERT_EQ(cudaResult, 0);
// z.tickWriteDevice();
// z.syncToHost();
// z.printIndexedBuffer("Random1");
ASSERT_EQ(exp, z);
// // verify results
// for (int e = 0; e < z.lengthOf(); e++)
// ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5);
// cudaFree(dExtraArgs);
// free allocated global device memory // free allocated global device memory
for(int i = 0; i < devicePtrs.size(); ++i) cudaFree(devicePtrs[i]); // cudaFree(dGen);
// delete cuda stream // delete cuda stream
cudaResult = cudaStreamDestroy(stream); ASSERT_EQ(0, cudaResult); // cudaResult = cudaStreamDestroy(stream); ASSERT_EQ(0, cudaResult);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -2977,42 +2965,42 @@ TEST_F(CudaBasicsTests1, execRandom_2) {
NDArray z('c', {2,5}, {100,100,100,100,100,100,100,100,100,100}, nd4j::DataType::DOUBLE); NDArray z('c', {2,5}, {100,100,100,100,100,100,100,100,100,100}, nd4j::DataType::DOUBLE);
NDArray exp('c', {10}, {0., 0., 0.3, 0., 0.5, 0., 0.7, 0., 0., 1.}, nd4j::DataType::DOUBLE); NDArray exp('c', {10}, {0., 0., 0.3, 0., 0.5, 0., 0.7, 0., 0., 1.}, nd4j::DataType::DOUBLE);
std::vector<double> extraArguments = {0.7}; ExtraArguments extraArguments({0.7});
nd4j::graph::RandomGenerator gen(119,5); nd4j::graph::RandomGenerator gen(119,5);
// prepare input arrays for prepareDataForCuda function // // prepare input arrays for prepareDataForCuda function
std::vector<std::pair<void*,size_t>> hostData; // std::vector<std::pair<void*,size_t>> hostData;
hostData.emplace_back(extraArguments.data(), extraArguments.size() * sizeof(double)); // 0 -- dimensions // hostData.emplace_back(extraArguments.data(), extraArguments.size() * sizeof(double)); // 0 -- dimensions
std::vector<void*> devicePtrs(hostData.size(), nullptr); // std::vector<void*> devicePtrs(hostData.size(), nullptr);
//
// create cuda stream and LaunchContext // create cuda stream and LaunchContext
cudaError_t cudaResult; cudaError_t cudaResult;
cudaStream_t stream; // cudaStream_t stream;
cudaResult = cudaStreamCreate(&stream); ASSERT_EQ(0, cudaResult); // cudaResult = cudaStreamCreate(&stream); ASSERT_EQ(0, cudaResult);
LaunchContext lc(&stream); LaunchContext* lc = x.getContext(); //(&stream);
// allocate required amount of global device memory and copy host data to it // allocate required amount of global device memory and copy host data to it
cudaResult = allocateDeviceMem(lc, devicePtrs, hostData); ASSERT_EQ(0, cudaResult); // cudaResult = allocateDeviceMem(lc, devicePtrs, hostData); ASSERT_EQ(0, cudaResult);
// call cuda kernel which calculates result // call cuda kernel which calculates result
NativeOpExecutioner::execRandom(&lc, nd4j::random::DropOut, NativeOpExecutioner::execRandom(lc, nd4j::random::DropOut,
&gen, &gen,
nullptr, x.getShapeInfo(), x.specialBuffer(), x.specialShapeInfo(), nullptr, x.getShapeInfo(), x.specialBuffer(), x.specialShapeInfo(),
nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(), nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
devicePtrs[0]); extraArguments.argumentsAsT(z.dataType()));
cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult); cudaResult = cudaStreamSynchronize(*lc->getCudaStream()); ASSERT_EQ(0, cudaResult);
z.tickWriteDevice(); z.tickWriteDevice();
z.syncToHost();
// verify results // verify results
for (int e = 0; e < z.lengthOf(); e++) for (int e = 0; e < z.lengthOf(); e++)
ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5); ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5);
// free allocated global device memory // free allocated global device memory
for(int i = 0; i < devicePtrs.size(); ++i) cudaFree(devicePtrs[i]); // for(int i = 0; i < devicePtrs.size(); ++i) cudaFree(devicePtrs[i]);
// delete cuda stream // delete cuda stream
cudaResult = cudaStreamDestroy(stream); ASSERT_EQ(0, cudaResult); // cudaResult = cudaStreamDestroy(stream); ASSERT_EQ(0, cudaResult);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -3061,44 +3049,45 @@ TEST_F(CudaBasicsTests1, execRandom_3) {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
TEST_F(CudaBasicsTests1, execRandom_4) { TEST_F(CudaBasicsTests1, execRandom_4) {
NDArray z('c', {2,5}, {1,2,3,4,5,6,7,8,9,10}, nd4j::DataType::DOUBLE); NDArray z('c', {2,5}, {1,2,3,4,5,6,7,8,9,10}, nd4j::DataType::FLOAT32);
NDArray exp('c', {10}, {2.373649, 2.239791, 1.887353, 2.488636, 2.068904, 2.281399, 1.828228, 2.228222, 2.490847, 1.669537}, nd4j::DataType::DOUBLE); NDArray exp('c', {10}, {2.373649, 2.281399, 2.239791, 1.828228, 1.887353, 2.228222, 2.488636, 2.490847, 2.068904, 1.669537}, nd4j::DataType::FLOAT32);
z.permutei({1,0}); z.permutei({1,0});
std::vector<double> extraArguments = {1.5, 2.5}; ExtraArguments extraArguments({1.5, 2.5});
nd4j::graph::RandomGenerator gen(119,5); nd4j::graph::RandomGenerator gen(119,5);
// prepare input arrays for prepareDataForCuda function // // prepare input arrays for prepareDataForCuda function
std::vector<std::pair<void*,size_t>> hostData; // std::vector<std::pair<void*,size_t>> hostData;
hostData.emplace_back(extraArguments.data(), extraArguments.size() * sizeof(double)); // 0 -- dimensions // hostData.emplace_back(extraArguments.data(), extraArguments.size() * sizeof(double)); // 0 -- dimensions
std::vector<void*> devicePtrs(hostData.size(), nullptr); // std::vector<void*> devicePtrs(hostData.size(), nullptr);
// create cuda stream and LaunchContext // create cuda stream and LaunchContext
cudaError_t cudaResult; // cudaError_t cudaResult;
cudaStream_t stream; // cudaStream_t stream;
cudaResult = cudaStreamCreate(&stream); ASSERT_EQ(0, cudaResult); // cudaResult = cudaStreamCreate(&stream); ASSERT_EQ(0, cudaResult);
LaunchContext lc(&stream); // LaunchContext lc(&stream);
//
// allocate required amount of global device memory and copy host data to it // // allocate required amount of global device memory and copy host data to it
cudaResult = allocateDeviceMem(lc, devicePtrs, hostData); ASSERT_EQ(0, cudaResult); // cudaResult = allocateDeviceMem(lc, devicePtrs, hostData); ASSERT_EQ(0, cudaResult);
auto context = z.getContext();
PointersManager pm(context, "execRandom4");
// call cuda kernel which calculates result // call cuda kernel which calculates result
NativeOpExecutioner::execRandom(&lc, nd4j::random::UniformDistribution, NativeOpExecutioner::execRandom(context, nd4j::random::UniformDistribution,
&gen, &gen,
nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(), nullptr, z.getShapeInfo(), z.specialBuffer(), z.specialShapeInfo(),
devicePtrs[0]); extraArguments.argumentsAsT(z.dataType()));
cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult); // cudaResult = cudaStreamSynchronize(stream); ASSERT_EQ(0, cudaResult);
z.tickWriteDevice(); z.tickWriteDevice();
// z.printIndexedBuffer("Output Uniform4");
// verify results // verify results
for (int e = 0; e < z.lengthOf(); e++) for (int e = 0; e < z.lengthOf(); e++)
ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5); ASSERT_NEAR(exp.e<double>(e), z.e<double>(e), 1e-5);
// free allocated global device memory // free allocated global device memory
for(int i = 0; i < devicePtrs.size(); ++i) cudaFree(devicePtrs[i]); // for(int i = 0; i < devicePtrs.size(); ++i) cudaFree(devicePtrs[i]);
// delete cuda stream // delete cuda stream
cudaResult = cudaStreamDestroy(stream); ASSERT_EQ(0, cudaResult); // cudaResult = cudaStreamDestroy(stream); ASSERT_EQ(0, cudaResult);
} }

View File

@ -1980,35 +1980,36 @@ TEST_F(NDArrayCudaBasicsTests, subarray_1)
NDArray x('c', {2,3,4}, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}, nd4j::DataType::FLOAT32); NDArray x('c', {2,3,4}, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}, nd4j::DataType::FLOAT32);
NDArray y('f', {2,3,4}, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}, nd4j::DataType::FLOAT32); NDArray y('f', {2,3,4}, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}, nd4j::DataType::FLOAT32);
Nd4jLong shapeExpX0[] = {1, 2, 12, 8192, -1, 99}; Nd4jLong shapeExpX0[] = {1, 2, 12, 8192, 1, 99};
float buffExpX0[] = {1.000000, 13.000000}; float buffExpX0[] = {1.000000, 13.000000};
Nd4jLong shapeExpX1[] = {1, 2, 12, 8192, -1, 99}; Nd4jLong shapeExpX1[] = {1, 2, 12, 8192, 1, 99};
float buffExpX1[] = {2.000000, 14.000000}; float buffExpX1[] = {2.000000, 14.000000};
Nd4jLong shapeExpX2[] = {3, 2, 1, 1, 12, 4, 1, 8192, -1, 99}; Nd4jLong shapeExpX2[] = {3, 2, 1, 1, 12, 4, 1, 8192, 1, 99};
float buffExpX2[] = {1.000000, 13.000000}; float buffExpX2[] = {1.000000, 13.000000};
Nd4jLong shapeExpX3[] = {2, 2, 4, 12, 1, 8192, -1, 99}; Nd4jLong shapeExpX3[] = {2, 2, 4, 12, 1, 8192, 1, 99};
float buffExpX3[] = {9.000000, 10.000000, 11.000000, 12.000000, 21.000000, 22.000000, 23.000000, 24.000000}; float buffExpX3[] = {9.000000, 10.000000, 11.000000, 12.000000, 21.000000, 22.000000, 23.000000, 24.000000};
Nd4jLong shapeExpX4[] = {3, 2, 1, 4, 12, 4, 1, 8192, -1, 99}; Nd4jLong shapeExpX4[] = {3, 2, 1, 4, 12, 4, 1, 8192, 1, 99};
float buffExpX4[] = {9.000000, 10.000000, 11.000000, 12.000000, 21.000000, 22.000000, 23.000000, 24.000000}; float buffExpX4[] = {9.000000, 10.000000, 11.000000, 12.000000, 21.000000, 22.000000, 23.000000, 24.000000};
Nd4jLong shapeExpX5[] = {2, 2, 3, 12, 4, 8192, -1, 99}; Nd4jLong shapeExpX5[] = {2, 2, 3, 12, 4, 8192, 1, 99};
float buffExpX5[] = {4.000000, 8.000000, 12.000000, 16.000000, 20.000000, 24.000000}; float buffExpX5[] = {4.000000, 8.000000, 12.000000, 16.000000, 20.000000, 24.000000};
Nd4jLong shapeExpY0[] = {1, 2, 1, 8192, -1, 99}; Nd4jLong shapeExpY0[] = {1, 2, 1, 8192, 1, 99};
float buffExpY0[] = {1.000000, 2.000000}; float buffExpY0[] = {1.000000, 2.000000};
Nd4jLong shapeExpY1[] = {1, 2, 1, 8192, -1, 99}; Nd4jLong shapeExpY1[] = {1, 2, 1, 8192, 1, 99};
float buffExpY1[] = {7.000000, 8.000000}; float buffExpY1[] = {7.000000, 8.000000};
Nd4jLong shapeExpY2[] = {3, 2, 1, 1, 1, 2, 6, 8192, -1, 102}; Nd4jLong shapeExpY2[] = {3, 2, 1, 1, 1, 2, 6, 8192, 1, 102};
float buffExpY2[] = {1.000000, 2.000000}; float buffExpY2[] = {1.000000, 2.000000};
Nd4jLong shapeExpY3[] = {2, 2, 4, 1, 6, 8192, -1, 99}; Nd4jLong shapeExpY3[] = {2, 2, 4, 1, 6, 8192, 1, 99};
float buffExpY3[] = {5.000000, 11.000000, 17.000000, 23.000000, 6.000000, 12.000000, 18.000000, 24.000000}; float buffExpY3[] = {5.000000, 11.000000, 17.000000, 23.000000, 6.000000, 12.000000, 18.000000, 24.000000};
Nd4jLong shapeExpY4[] = {3, 2, 1, 4, 1, 2, 6, 8192, -1, 102}; Nd4jLong shapeExpY4[] = {3, 2, 1, 4, 1, 2, 6, 8192, 1, 102};
float buffExpY4[] = {5.000000, 11.000000, 17.000000, 23.000000, 6.000000, 12.000000, 18.000000, 24.000000}; float buffExpY4[] = {5.000000, 11.000000, 17.000000, 23.000000, 6.000000, 12.000000, 18.000000, 24.000000};
Nd4jLong shapeExpY5[] = {2, 2, 3, 1, 2, 8192, -1, 99}; Nd4jLong shapeExpY5[] = {2, 2, 3, 1, 2, 8192, 1, 99};
float buffExpY5[] = {19.000000, 21.000000, 23.000000, 20.000000, 22.000000, 24.000000}; float buffExpY5[] = {19.000000, 21.000000, 23.000000, 20.000000, 22.000000, 24.000000};
NDArray x0 = x(0, {1,2}); NDArray x0 = x(0, {1,2});
NDArray xExp(buffExpX0, shapeExpX0); NDArray xExp(buffExpX0, shapeExpX0);
ASSERT_TRUE(xExp.isSameShape(x0)); ASSERT_TRUE(xExp.isSameShape(x0));
ASSERT_TRUE(xExp.equalsTo(x0)); ASSERT_TRUE(xExp.equalsTo(x0));
// for(int i = 0; i < shape::shapeInfoLength(x0.rankOf()); ++i) // for(int i = 0; i < shape::shapeInfoLength(x0.rankOf()); ++i)
@ -2029,8 +2030,8 @@ TEST_F(NDArrayCudaBasicsTests, subarray_1)
NDArray x2 = x(0, {1,2}, true); NDArray x2 = x(0, {1,2}, true);
NDArray x2Exp(buffExpX2, shapeExpX2); NDArray x2Exp(buffExpX2, shapeExpX2);
ASSERT_TRUE(x2Exp.isSameShape(x2)); ASSERT_TRUE(x2Exp.isSameShape(x2));
x2.printBuffer("X2"); // x2.printBuffer("X2");
x2Exp.printBuffer("X2 EXPECT"); // x2Exp.printBuffer("X2 EXPECT");
ASSERT_TRUE(x2Exp.equalsTo(x2)); ASSERT_TRUE(x2Exp.equalsTo(x2));
// for(int i = 0; i < shape::shapeInfoLength(x2.rankOf()); ++i) // for(int i = 0; i < shape::shapeInfoLength(x2.rankOf()); ++i)
// ASSERT_TRUE(x2.getShapeInfo()[i] == shapeExpX2[i]); // ASSERT_TRUE(x2.getShapeInfo()[i] == shapeExpX2[i]);
@ -2076,34 +2077,49 @@ TEST_F(NDArrayCudaBasicsTests, subarray_1)
// ASSERT_TRUE(y0.e<float>(i) == buffExpY0[i]); // ASSERT_TRUE(y0.e<float>(i) == buffExpY0[i]);
NDArray y1 = y(1, {1,2}); NDArray y1 = y(1, {1,2});
for(int i = 0; i < shape::shapeInfoLength(y1.rankOf()); ++i) NDArray y1Exp(buffExpY1, shapeExpY1);
ASSERT_TRUE(y1.getShapeInfo()[i] == shapeExpY1[i]); ASSERT_TRUE(y1Exp.isSameShape(y1));
for(int i = 0; i < y1.lengthOf(); ++i) ASSERT_TRUE(y1Exp.equalsTo(y1));
ASSERT_TRUE(y1.e<float>(i) == buffExpY1[i]); // for(int i = 0; i < shape::shapeInfoLength(y1.rankOf()); ++i)
// ASSERT_TRUE(y1.getShapeInfo()[i] == shapeExpY1[i]);
// for(int i = 0; i < y1.lengthOf(); ++i)
// ASSERT_TRUE(y1.e<float>(i) == buffExpY1[i]);
NDArray y2 = y(0, {1,2}, true); NDArray y2 = y(0, {1,2}, true);
for(int i = 0; i < shape::shapeInfoLength(y2.rankOf()); ++i) NDArray y2Exp(buffExpY2, shapeExpY2);
ASSERT_TRUE(y2.getShapeInfo()[i] == shapeExpY2[i]); ASSERT_TRUE(y2Exp.isSameShape(y2));
for(int i = 0; i < y2.lengthOf(); ++i) ASSERT_TRUE(y2Exp.equalsTo(y2));
ASSERT_TRUE(y2.e<float>(i) == buffExpY2[i]); // for(int i = 0; i < shape::shapeInfoLength(y2.rankOf()); ++i)
// ASSERT_TRUE(y2.getShapeInfo()[i] == shapeExpY2[i]);
// for(int i = 0; i < y2.lengthOf(); ++i)
// ASSERT_TRUE(y2.e<float>(i) == buffExpY2[i]);
NDArray y3 = y(2, {1}); NDArray y3 = y(2, {1});
for(int i = 0; i < shape::shapeInfoLength(y3.rankOf()); ++i) NDArray y3Exp(buffExpY3, shapeExpY3);
ASSERT_TRUE(y3.getShapeInfo()[i] == shapeExpY3[i]); ASSERT_TRUE(y3Exp.isSameShape(y3));
for(int i = 0; i < y3.lengthOf(); ++i) ASSERT_TRUE(y3Exp.equalsTo(y3));
ASSERT_TRUE(y3.e<float>(i) == buffExpY3[i]); // for(int i = 0; i < shape::shapeInfoLength(y3.rankOf()); ++i)
// ASSERT_TRUE(y3.getShapeInfo()[i] == shapeExpY3[i]);
// for(int i = 0; i < y3.lengthOf(); ++i)
// ASSERT_TRUE(y3.e<float>(i) == buffExpY3[i]);
NDArray y4 = y(2, {1}, true); NDArray y4 = y(2, {1}, true);
for(int i = 0; i < shape::shapeInfoLength(y4.rankOf()); ++i) NDArray y4Exp = NDArrayFactory::create<float>('f', {2,1,4}, {5, 6, 11, 12, 17, 18, 23, 24});
ASSERT_TRUE(y4.getShapeInfo()[i] == shapeExpY4[i]); ASSERT_TRUE(y4Exp.isSameShape(y4));
for(int i = 0; i < y4.lengthOf(); ++i) ASSERT_TRUE(y4Exp.equalsTo(y4));
ASSERT_TRUE(y4.e<float>(i) == buffExpY4[i]); // for(int i = 0; i < shape::shapeInfoLength(y4.rankOf()); ++i)
// ASSERT_TRUE(y4.getShapeInfo()[i] == shapeExpY4[i]);
// for(int i = 0; i < y4.lengthOf(); ++i)
// ASSERT_TRUE(y4.e<float>(i) == buffExpY4[i]);
NDArray y5 = y(3, {2}); NDArray y5 = y(3, {2});
for(int i = 0; i < shape::shapeInfoLength(y5.rankOf()); ++i) NDArray y5Exp(buffExpY5, shapeExpY5);
ASSERT_TRUE(y5.getShapeInfo()[i] == shapeExpY5[i]); ASSERT_TRUE(y5Exp.isSameShape(y5));
for(int i = 0; i < y5.lengthOf(); ++i) ASSERT_TRUE(y5Exp.equalsTo(y5));
ASSERT_TRUE(y5.e<float>(i) == buffExpY5[i]); // for(int i = 0; i < shape::shapeInfoLength(y5.rankOf()); ++i)
// ASSERT_TRUE(y5.getShapeInfo()[i] == shapeExpY5[i]);
// for(int i = 0; i < y5.lengthOf(); ++i)
// ASSERT_TRUE(y5.e<float>(i) == buffExpY5[i]);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -248,8 +248,8 @@ TEST_F(RNGTests, Test_Gaussian_21) {
RandomLauncher::fillGaussian(LaunchContext::defaultContext(), _rngA, &x0, 0.0f, 1.0f); RandomLauncher::fillGaussian(LaunchContext::defaultContext(), _rngA, &x0, 0.0f, 1.0f);
RandomLauncher::fillGaussian(LaunchContext::defaultContext(), _rngB, &x1, 0.0f, 1.0f); RandomLauncher::fillGaussian(LaunchContext::defaultContext(), _rngB, &x1, 0.0f, 1.0f);
//x0.printIndexedBuffer("x0"); x0.printIndexedBuffer("x0");
//x1.printIndexedBuffer("x1"); x1.printIndexedBuffer("x1");
ASSERT_TRUE(x0.equalsTo(&x1)); ASSERT_TRUE(x0.equalsTo(&x1));
ASSERT_FALSE(x0.equalsTo(nexp0)); ASSERT_FALSE(x0.equalsTo(nexp0));
@ -272,7 +272,7 @@ TEST_F(RNGTests, Test_Gaussian_21) {
delete result; delete result;
} }
#ifndef DEBUG_BUILD #ifdef DEBUG_BUILD
TEST_F(RNGTests, Test_Gaussian_22) { TEST_F(RNGTests, Test_Gaussian_22) {
auto x0 = NDArrayFactory::create<float>('c', {10000, 1000}); auto x0 = NDArrayFactory::create<float>('c', {10000, 1000});
auto x1 = NDArrayFactory::create<float>('c', {10000, 1000}); auto x1 = NDArrayFactory::create<float>('c', {10000, 1000});
@ -307,11 +307,12 @@ TEST_F(RNGTests, Test_Gaussian_3) {
RandomLauncher::fillGaussian(LaunchContext::defaultContext(), _rngA, &x0, 0.0, 1.0); RandomLauncher::fillGaussian(LaunchContext::defaultContext(), _rngA, &x0, 0.0, 1.0);
auto mean = x0.meanNumber().e<double>(0); auto mean = x0.meanNumber(); //.e<double>(0);
auto stdev = x0.varianceNumber(nd4j::variance::SummaryStatsStandardDeviation, false).e<double>(0); auto stdev = x0.varianceNumber(nd4j::variance::SummaryStatsStandardDeviation, false);//.e<double>(0);
auto meanExp = NDArrayFactory::create<double>(0.);
ASSERT_NEAR(0.0, mean, 1e-3); auto devExp = NDArrayFactory::create<double>(1.);
ASSERT_NEAR(1.0, stdev, 1e-3); ASSERT_TRUE(meanExp.equalsTo(mean, 1.e-3));
ASSERT_TRUE(devExp.equalsTo(stdev, 1.e-3));
} }
TEST_F(RNGTests, Test_LogNormal_1) { TEST_F(RNGTests, Test_LogNormal_1) {
@ -455,7 +456,7 @@ TEST_F(RNGTests, Test_Truncated_22) {
// deviation.printIndexedBuffer("Deviation should be 4.0"); // deviation.printIndexedBuffer("Deviation should be 4.0");
//x1.printIndexedBuffer("Distribution TN"); //x1.printIndexedBuffer("Distribution TN");
ASSERT_NEAR(mean.e<float>(0), 2.f, 0.01); ASSERT_NEAR(mean.e<float>(0), 2.f, 0.01);
ASSERT_NEAR(deviation.e<float>(0), 4.f, 0.5); ASSERT_NEAR(deviation.e<float>(0), 4.f, 0.52);
nd4j::ops::moments op; nd4j::ops::moments op;
auto result = op.execute({&x0}, {}, {}, {}, false, nd4j::DataType::FLOAT32); auto result = op.execute({&x0}, {}, {}, {}, false, nd4j::DataType::FLOAT32);
// result->at(0)->printBuffer("MEAN"); // result->at(0)->printBuffer("MEAN");