// // // Copyright (c) Microsoft Corporation. All rights reserved. // // #pragma once #ifdef _WIN32 #ifdef MATH_EXPORTS #define MATH_API __declspec(dllexport) #else #define MATH_API __declspec(dllimport) #endif #else // no DLLs on Linux #define MATH_API #endif #include "Basics.h" #include #include #define DEVICEID_TYPE int // and the following magic values #define CPUDEVICE (DEVICEID_TYPE)-1 // device is the CPU #define DEVICEID_NOTYETDETERMINED (DEVICEID_TYPE)-3 // not yet set #define DEVICEID_AUTO (DEVICEID_TYPE)-4 // device should be picked automatically #define AUTOPLACEMATRIX (DEVICEID_TYPE)1000 // used in parameters only #define EPS_IN_INVERSE 1e-30f // 1e-37 is the only guaranteed precision #define EPS_IN_LOG 1e-37f // 1e-37 is the only guaranteed precision #define LOG_OF_EPS_IN_LOG -85.1f // log(EPS_IN_LOG) #define LOG10_OF_EPS_IN_LOG -37 // log_10(EPS_IN_LOG) #define LZERO -10e10 #define MINLOGEXP -9.2103 #define LSMALL -0.5E10 #define GPUSPARSE_INDEX_TYPE int //cuSparse only supports int array indexes #define CPUSPARSE_INDEX_TYPE int //to be consistent with cuSparse but limited the possible size of the matrix. MATH_API DEVICEID_TYPE EnforceOneGPUOnly(DEVICEID_TYPE requestedDeviceId); namespace Microsoft { namespace MSR { namespace CNTK { // ----------------------------------------------------------------------- // ElementWiseOperator -- This enum represents which function to apply. // This is shared between all matrix types and tensors. // ----------------------------------------------------------------------- enum ElementWiseOperator { // nullary opConstOne, // unary (or binary with constant parameter) opCopy, opNegate, opNot, opAbs, opSigmoid, opTanh, opSqrt, opExp, opLog, opLinearRectifier, opCosine, // unary ops for use by Matrix class only (there is no TensorView implementation) opSigmoidDerivative, opLinearRectifierDerivative, opNegativeSine, // binary opSum, opDifference, opElementwiseProduct, opElementwiseQuotient, opLogSum, opMax, opMin, opEQ, opNE, opGT, opLT, opGE, opLE, opAnd, opOr, opXor, opMaskNegative, opElementwiseProductWithSigmoidDerivativeFromOutput, opElementwiseProductWithTanhDerivativeFromOutput, opElementwiseProductWithLinearRectifierDerivativeFromOutput, opElementwiseProductWithLogDerivativeFromOutput, opElementwiseProductWithCosDerivative, // binary ops for indexing //opIndex, // ternary opCond/*a ? b : c*/, opClip/*clip a within interval b..c*/ // Note: not all that's implemented in CNTK ComputationNodes has an opcode yet. }; // helper to apply a C macro for all operations of each kind #define ForAllNullaryOps(Macro) \ Macro(ConstOne); #define ForAllUnaryOps(Macro) \ Macro(Copy); \ Macro(Negate); Macro(Not); \ Macro(Abs); \ Macro(Sigmoid); Macro(Tanh); Macro(Sqrt); Macro(Exp); Macro(Log); Macro(LinearRectifier); Macro(Cosine); #define ForAllBinaryOps(Macro) \ Macro(Sum); Macro(Difference); Macro(ElementwiseProduct); Macro(ElementwiseQuotient); \ Macro(LogSum); Macro(Max); Macro(Min); \ Macro(EQ); Macro(NE); Macro(GT); Macro(LT); Macro(GE); Macro(LE); \ Macro(And); Macro(Or); Macro(Xor);\ Macro(MaskNegative); \ Macro(ElementwiseProductWithSigmoidDerivativeFromOutput); Macro(ElementwiseProductWithTanhDerivativeFromOutput); \ Macro(ElementwiseProductWithLinearRectifierDerivativeFromOutput); Macro(ElementwiseProductWithLogDerivativeFromOutput); Macro(ElementwiseProductWithCosDerivative); \ //Macro(Index); #define ForAllTernaryOps(Macro) \ Macro(Cond); Macro(Clip); // ----------------------------------------------------------------------- // various enums to describe // ----------------------------------------------------------------------- enum MatrixFlagBitPosition { bitPosRowMajor = 0, // row major matrix bitPosSparse = 1, // sparse matrix (COO if uncompressed) bitPosCompressed = 2, // a compressed sparse format (CSC/CSR) bitPosDontOwnBuffer = 3, // buffer is not owned by this matrix bitPosSetValueOnDevice = 4, // in a setValue situation, the copy from buffer is already on the device }; enum MatrixFormat { matrixFormatDense = 0, // default is dense matrixFormatColMajor = 0, // default is column major matrixFormatRowMajor = 1< class BaseMatrix { public: MatrixFormat GetFormat() const {return m_format;} void SetFormat(MatrixFormat format) {m_format = format;} size_t GetNumRows() const {return m_numRows;} size_t GetNumCols() const {return m_numCols;} size_t GetNumElements() const {return m_numRows * m_numCols;} bool IsEmpty() const {return m_numRows == 0 || m_numCols == 0; } ElemType* GetArray() {return m_pArray;} void SetArray(ElemType *parray) { m_pArray = parray; } virtual DEVICEID_TYPE GetComputeDeviceId() const {return m_computeDevice;} void SetComputeDeviceId(const DEVICEID_TYPE computeId) const {m_computeDevice = computeId;} bool OwnBuffer() const {return !m_externalBuffer;} void SetOwnBuffer(bool own) {m_externalBuffer = !own;} wchar_t* GetMatrixName() const { return m_matrixName; } size_t NzCount() const {return m_nz;} void SetNzCount(const size_t nz) { m_nz = nz; } size_t GetSizeAllocated() const { return m_elemSizeAllocated; } void VerifySize(size_t rows, size_t cols) { if (rows != GetNumRows() || cols != GetNumCols()) LogicError("VerifySize: expected matrix size %lu x %lu, but it is %lu x %lu", rows, cols, GetNumRows(), GetNumCols()); } void SetMatrixName(const wchar_t* s) { Clear(); if (s!=nullptr) { size_t n = wcslen(s); m_matrixName = new wchar_t[n+1]; wmemcpy(m_matrixName,s,n+1); } } BaseMatrix() { m_numRows = m_numCols = m_elemSizeAllocated = 0; m_pArray = NULL; m_matrixName = NULL; m_format = matrixFormatDense; m_externalBuffer = false; m_nz = 0; m_computeDevice = CPUDEVICE; } ~BaseMatrix() { Clear(); } protected: void Clear() { if (m_matrixName!=nullptr) { delete[] m_matrixName; m_matrixName = nullptr; } } protected: size_t m_numRows; size_t m_numCols; size_t m_elemSizeAllocated; size_t m_sliceViewOffset; // this is used to get a column slice view of a matrix in the Sparse CSC format MatrixFormat m_format; bool m_externalBuffer; // is the buffer used by this matrix, ElemType *m_pArray; mutable DEVICEID_TYPE m_computeDevice; //current GPU device Id or CPUDEVICE size_t m_nz; //Number of non-zero elements for sparse matrices (unused in other formats) wchar_t* m_matrixName; }; }}}