https://github.com/Microsoft/CNTK
Raw File
Tip revision: 5c3f708097bdcdaf2c06d2aa8a9b3fdc772ae27a authored by Mark Hillebrand on 18 January 2016, 08:36:30 UTC
License change
Tip revision: 5c3f708
CommonMatrix.h
//
// <copyright file="CommonMatrix.h" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
#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 <string>
#include <stdint.h>

#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
    {
        // unary (or binary with constant parameter)
        opCopy,
        opNegate, opNot,
        opAbs,
        opSigmoid, opSigmoidDerivative, opTanh, opSqrt, opExp, opLog, opLinearRectifierDerivative, opCosine, opNegativeSine,
        // these are not implemented yet:
        opSaturateBetaAlpha, opSumAlpha, opSubDifferenceToAlpha, opSubDifferenceFromAlpha,
        // binary
        opSum, opDifference, opElementwiseProduct, opElementwiseQuotient,
        opLogSum, opMax, opMin,
        opEQ, opNE, opGT, opLT, opGE, opLE,
        opMaskNegative,
        // ternary
        opCond
        // Note: not all of the above are actually implement at present; and not all that's implemented has an opcode.
    };

    // helper to apply a C macro for all operations of each kind
#define ForAllUnaryOps(Macro) \
    Macro(Copy); \
    Macro(Negate); Macro(Not); \
    Macro(Abs); \
    Macro(Sigmoid); Macro(SigmoidDerivative); Macro(Tanh); Macro(Sqrt); Macro(Exp); Macro(Log); Macro(LinearRectifierDerivative); Macro(Cosine); Macro(NegativeSine);

#define ForAllParameterizedUnaryOps(Macro) \
    Macro(SaturateBetaAlpha); Macro(SumAlpha); Macro(SubDifferenceToAlpha); Macro(SubDifferenceFromAlpha);

#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(MaskNegative);

#define ForAllTernaryOps(Macro) \
    Macro(Cond);

    // -----------------------------------------------------------------------
    // 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<<bitPosRowMajor, // row major matrix
        matrixFormatSparse = 1<<bitPosSparse, // sparse matrix
        matrixFormatCompressed = 1<<bitPosCompressed, // a compressed sparse format (CSC/CSR/COO)
        matrixFormatDenseColMajor = matrixFormatDense + matrixFormatColMajor,
        matrixFormatDenseRowMajor = matrixFormatDense + matrixFormatRowMajor,
        matrixFormatSparseCSC = matrixFormatSparse + matrixFormatColMajor + matrixFormatCompressed,
        matrixFormatSparseCSR = matrixFormatSparse + matrixFormatRowMajor + matrixFormatCompressed,
        matrixFormatSparseOther = matrixFormatSparse + matrixFormatRowMajor, // currently used for CPU sparse format, will change to CSC/CSR eventually
        matrixFormatMask = matrixFormatRowMajor + matrixFormatSparse + matrixFormatCompressed,// mask that covers all the 
        matrixFormatSparseBlockCol, //col block based sparse matrix
        matrixFormatSparseBlockRow, //row block based sparse matrix
    };

    // common matrix flags for use on all matrices
    enum MatrixFlags
    {
        // first bits of matrix flags are MatrixFormat
        matrixFlagNormal = 0,
        matrixFlagDontOwnBuffer = 1<<bitPosDontOwnBuffer, // the matrix memory pointers are externally managed, don't allocate/free or attempt to copy to another location
        matrixFlagSetValueOnDevice = 1<<bitPosSetValueOnDevice, // SetValue() call has a buffer that is already on the device
    };

    // -----------------------------------------------------------------------
    // BaseMatrix -- base class for all matrix types (CPU, GPU) x (dense, sparse)
    // -----------------------------------------------------------------------

    template<class ElemType>
    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;
    };
}}}
back to top