https://github.com/Microsoft/CNTK
Raw File
Tip revision: 8a0974ecfb5a97afa8437876c0f911a3601c7cba authored by Frank Seide on 29 January 2016, 18:53:16 UTC
fixed an incorrect consistency check in TrainOrAdaptModel()
Tip revision: 8a0974e
ConvolutionEngine.h
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
//

#pragma once

// REVIEW alexeyk: this seems to be repeated all over the CNTKMathDll.
#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 "Matrix.h"
#include "TensorShape.h" // for ImageLayoutKind

namespace Microsoft { namespace MSR { namespace CNTK {

// REVIEW alexeyk: this is a temp class until we have generic tensor suport in CNTK.
class ConvolutionTensor4D
{
public:
    size_t w() const
    {
        return m_w;
    }
    size_t h() const
    {
        return m_h;
    }
    size_t c() const
    {
        return m_c;
    }
    size_t n() const
    {
        return m_n;
    }
    virtual void setN(size_t n)
    {
        m_n = n;
    }

public:
    ConvolutionTensor4D(size_t w = 1, size_t h = 1, size_t c = 1, size_t n = 1)
    {
        m_w = w;
        m_h = h;
        m_c = c;
        m_n = n;
    }

public:
    virtual ~ConvolutionTensor4D() = default;
    // Deleting copy ctor/assignment as derived objects may contain non-copyable state.
    ConvolutionTensor4D(const ConvolutionTensor4D&) = delete;
    ConvolutionTensor4D& operator=(const ConvolutionTensor4D&) = delete;
    // REVIEW alexeyk: Have to implement move ctor explicitly as VS2013 does not support default move ctors.
    // ConvolutionTensor4D(ConvolutionTensor4D&&);
    // ConvolutionTensor4D& operator=(ConvolutionTensor4D&&);

private:
    size_t m_w;
    size_t m_h;
    size_t m_c;
    size_t m_n;
};

class ConvolutionFilter
{
public:
    size_t w() const
    {
        return m_w;
    }
    size_t h() const
    {
        return m_h;
    }
    size_t c() const
    {
        return m_c;
    }
    size_t k() const
    {
        return m_k;
    }

public:
    ConvolutionFilter(size_t w = 1, size_t h = 1, size_t c = 1, size_t k = 1)
    {
        m_w = w;
        m_h = h;
        m_c = c;
        m_k = k;
    }

public:
    virtual ~ConvolutionFilter() = default;

    // Deleting copy ctor/assignment as derived objects may contain non-copyable state.
    ConvolutionFilter(const ConvolutionFilter&) = delete;
    ConvolutionFilter& operator=(const ConvolutionFilter&) = delete;

private:
    size_t m_w;
    size_t m_h;
    size_t m_c;
    size_t m_k;
};

// ConvolutionDescriptor describes properties specific to convolution application.
class ConvolutionDescriptor
{
public:
    // Horizontal stride (in w-dimension).
    size_t wStride() const
    {
        return m_wStride;
    }
    // Vertical stride (in h-dimension).
    size_t hStride() const
    {
        return m_hStride;
    }
    bool padding() const
    {
        return m_padding;
    }

public:
    ConvolutionDescriptor(size_t wStride = 1, size_t hStride = 1, bool padding = false)
    {
        m_wStride = wStride;
        m_hStride = hStride;
        m_padding = padding;
    }

public:
    virtual ~ConvolutionDescriptor() = default;
    // Deleting copy ctor/assignment as derived objects may contain non-copyable state.
    ConvolutionDescriptor(const ConvolutionDescriptor&) = delete;
    ConvolutionDescriptor& operator=(const ConvolutionDescriptor&) = delete;

private:
    size_t m_wStride;
    size_t m_hStride;
    bool m_padding;
};

// PoolingDescriptor describes properties specific to convolution application.
class PoolingDescriptor
{
public:
    enum class PoolKind
    {
        Max,
        Average
    };

    PoolKind kind() const
    {
        return m_kind;
    }
    // Pooling window size.
    size_t w() const
    {
        return m_w;
    }
    size_t h() const
    {
        return m_h;
    }
    // Horizontal stride (in w-dimension).
    size_t wStride() const
    {
        return m_wStride;
    }
    // Vertical stride (in h-dimension).
    size_t hStride() const
    {
        return m_hStride;
    }
    // Horizontal pad (in w-dimension).
    size_t wPad() const
    {
        return m_wPad;
    }
    // Vertical pad (in h-dimension).
    size_t hPad() const
    {
        return m_hPad;
    }

public:
    PoolingDescriptor(PoolKind kind, size_t w, size_t h, size_t wStride, size_t hStride, size_t wPad, size_t hPad)
    {
        m_kind = kind;
        m_w = w;
        m_h = h;
        m_wStride = wStride;
        m_hStride = hStride;
        m_wPad = wPad;
        m_hPad = hPad;
    }

public:
    virtual ~PoolingDescriptor() = default;
    // Deleting copy ctor/assignment as derived objects may contain non-copyable state.
    PoolingDescriptor(const PoolingDescriptor&) = delete;
    PoolingDescriptor& operator=(const PoolingDescriptor&) = delete;

private:
    PoolKind m_kind;
    size_t m_w;
    size_t m_h;
    size_t m_wStride;
    size_t m_hStride;
    size_t m_wPad;
    size_t m_hPad;
};

template <class ElemType>
class MATH_API ConvolutionEngine
{
public:
    using Tensor4D = ConvolutionTensor4D;
    using Filter = ConvolutionFilter;
    using ConvDesc = ConvolutionDescriptor;
    using Mat = Matrix<ElemType>;

public:
    ConvolutionEngine() = default;
    virtual ~ConvolutionEngine() = default;

    virtual void Forward(const Tensor4D& inT, const Mat& in, const Filter& filterT, const Mat& filter, const ConvDesc& convDesc,
                         const Tensor4D& outT, Mat& out, Mat& workspace) = 0;

    virtual void BackwardData(const Tensor4D& srcGradT, const Mat& srcGrad, const Filter& filterT, const Mat& filter, const ConvDesc& convDesc,
                              const Tensor4D& gradT, Mat& grad, Mat& workspace) = 0;

    virtual void BackwardFilter(const Tensor4D& srcGradT, const Mat& srcGrad, const Tensor4D& inT, const Mat& in, const ConvDesc& convDesc,
                                const Filter& filterT, Mat& filter, bool allowReuse, Mat& workspace) = 0;

    virtual void AddBias(const Tensor4D& outT, const Mat& out, const Tensor4D& biasT, const Mat& bias, Mat& dst) = 0;
    virtual void BackwardBias(const Tensor4D& srcGradT, const Mat& srcGrad, const Tensor4D& biasT, Mat& biasGrad) = 0;

    virtual void NormalizeBatch(const Tensor4D& inT, const Mat& in, const Tensor4D& scaleBiasT, const Mat& scale, const Mat& bias,
                                bool spatial, double expAvgFactor, Mat& runMean, Mat& runInvStdDev, Mat& out, Mat& saveMean, Mat& saveInvStdDev) = 0;

    virtual void NormalizeBatchInference(const Tensor4D& inT, const Mat& in, const Tensor4D& scaleBiasT, const Mat& scale, const Mat& bias,
                                         bool spatial, const Mat& runMean, const Mat& runInvStdDev, Mat& out) = 0;

    virtual void BackwardNormalizeBatch(const Tensor4D& inT, const Mat& in, const Mat& srcGrad, Mat& grad,
                                        const Tensor4D& scaleBiasT, const Mat& scale, bool spatial, const Mat& saveMean, const Mat& saveInvStdDev,
                                        Mat& scaleGrad, Mat& biasGrad) = 0;

public:
    ConvolutionEngine(const ConvolutionEngine&) = delete;
    ConvolutionEngine& operator=(const ConvolutionEngine&) = delete;
    ConvolutionEngine(ConvolutionEngine&&) = delete;
    ConvolutionEngine& operator=(ConvolutionEngine&&) = delete;
};

template <class ElemType>
class MATH_API PoolingEngine
{
public:
    using Tensor4D = ConvolutionTensor4D;
    using PoolDesc = PoolingDescriptor;
    using Mat = Matrix<ElemType>;

public:
    PoolingEngine() = default;
    virtual ~PoolingEngine() = default;

    virtual void Forward(const Tensor4D& inT, const Mat& in, const PoolDesc& poolDesc, const Tensor4D& outT, Mat& out) = 0;
    virtual void Backward(const Tensor4D& outT, const Mat& out, const Mat& srcGrad, const PoolDesc& poolDesc, const Tensor4D& inT, const Mat& in, Mat& grad) = 0;

public:
    PoolingEngine(const PoolingEngine&) = delete;
    PoolingEngine& operator=(const PoolingEngine&) = delete;
    PoolingEngine(PoolingEngine&&) = delete;
    PoolingEngine& operator=(PoolingEngine&&) = delete;
};

template <class ElemType>
class MATH_API ConvolutionEngineFactory
{
public:
    using Tensor4D = ConvolutionTensor4D;
    using Tensor4DPtr = std::unique_ptr<Tensor4D>;
    using Filter = ConvolutionFilter;
    using FilterPtr = std::unique_ptr<ConvolutionFilter>;
    using ConvDesc = ConvolutionDescriptor;
    using ConvDescPtr = std::unique_ptr<ConvolutionDescriptor>;
    using PoolDesc = PoolingDescriptor;
    using PoolDescPtr = std::unique_ptr<PoolingDescriptor>;

    using ConvEnginePtr = std::unique_ptr<ConvolutionEngine<ElemType>>;
    using PoolEnginePtr = std::unique_ptr<PoolingEngine<ElemType>>;

public:
    ConvolutionEngineFactory() = default;
    virtual ~ConvolutionEngineFactory() = default;

    virtual Tensor4DPtr CreateTensor(size_t w, size_t h, size_t c, size_t n) = 0;
    virtual FilterPtr CreateFilter(size_t w, size_t h, size_t c, size_t k) = 0;
    virtual ConvDescPtr CreateConvDescriptor(const Tensor4D& inT, const Filter& filterT,
                                             size_t wStride, size_t hStride, bool padding) = 0;
    virtual PoolDescPtr CreatePoolDescriptor(PoolDesc::PoolKind kind, size_t w, size_t h, size_t wStride, size_t hStride, size_t wPad, size_t hPad) = 0;
    // virtual Tensor4DPtr CreateLrnDescriptor() = 0;

    virtual ConvEnginePtr CreateConvEngine(DEVICEID_TYPE deviceId, size_t maxTempMemSizeInSamples) = 0;
    virtual PoolEnginePtr CreatePoolEngine(DEVICEID_TYPE deviceId) = 0;

    enum class EngineType
    {
        Auto,
        CuDnn,
        Legacy
    };
    static std::unique_ptr<ConvolutionEngineFactory<ElemType>> Create(DEVICEID_TYPE deviceId, EngineType engType, ImageLayoutKind imageLayoutKind);

public:
    ConvolutionEngineFactory(const ConvolutionEngineFactory&) = delete;
    ConvolutionEngineFactory& operator=(const ConvolutionEngineFactory&) = delete;
    ConvolutionEngineFactory(ConvolutionEngineFactory&&) = delete;
    ConvolutionEngineFactory& operator=(ConvolutionEngineFactory&&) = delete;
};
} } }
back to top