// TODO: This could actually be strided? const char* NDMask::DataBuffer() const { // First make sure that the underlying matrix is on the right device auto matrix = GetMatrix(); matrix->TransferToDeviceIfNotThere(AsCNTKImplDeviceId(m_device), true); return matrix->Data(); }
static Matrix<char>* AllocateMatrix(const NDShape& viewShape, const DeviceDescriptor& device) { auto matrixDims = GetMatrixDimensions(viewShape); auto maskMatrix = new Matrix<char>(matrixDims.first, matrixDims.second, AsCNTKImplDeviceId(device)); maskMatrix->SetValue(1); return maskMatrix; }
const ElementType* NDArrayView::DataBuffer() const { if (AsDataType<ElementType>() != m_dataType) LogicError("The specified ElementType %s does not match the DataType %s", typeid(ElementType).name(), DataTypeName(m_dataType)); if (IsSparse()) InvalidArgument("DataBuffer/WritableDataBuffer methods can only be called for NDArrayiew objects with dense storage format"); // First make sure that the underlying matrix is on the right device auto matrix = GetMatrix<ElementType>(); matrix->TransferToDeviceIfNotThere(AsCNTKImplDeviceId(m_device), true); return matrix->Data(); }
/*static*/ NDArrayViewPtr Variable::CreateValueFromParameterInitializer(const NDShape& shape, const ParameterInitializer& initConfig, const DeviceDescriptor& device) { auto dataType = AsDataType<ElementType>(); auto value = MakeSharedObject<NDArrayView>(dataType, shape, device); auto valueMatrix = value->template GetWritableMatrix<ElementType>(); auto initializerType = initConfig[InitializerTypeAttributeName].Value<std::wstring>(); if (initializerType == Microsoft::MSR::CNTK::ConstantInitializerTypeName) { auto constantInitValue = initConfig[ValueAttributeName].Value<double>(); valueMatrix->SetValue((ElementType)constantInitValue); } else if (initializerType == Microsoft::MSR::CNTK::BilinearInitializerTypeName) { auto kernelWidth = initConfig[KernelWidthAttributeName].Value<size_t>(); auto kernelHeight = initConfig[KernelHeightAttributeName].Value<size_t>(); Microsoft::MSR::CNTK::LearnableParameter<ElementType>::InitBilinear(*valueMatrix, AsTensorShape(shape), kernelWidth, kernelHeight, AsCNTKImplDeviceId(device)); } else { auto randomSeed = (unsigned long)initConfig[RandomSeedAttributeName].Value<size_t>(); if (randomSeed == SentinelValueForAutoSelectRandomSeed) randomSeed = s_currentRandomSeed++; auto scale = initConfig[ScaleAttributeName].Value<double>(); int outputRank = DefaultParamInitOutputRank, filterRank = DefaultParamInitFilterRank; if (initializerType != Microsoft::MSR::CNTK::UniformInitializerTypeName) { outputRank = initConfig[OutputRankAttributeName].Value<int>(); filterRank = initConfig[FilterRankAttributeName].Value<int>(); if (outputRank == SentinelValueForInferParamInitRank) outputRank = DefaultParamInitOutputRank; if (filterRank == SentinelValueForInferParamInitRank) filterRank = DefaultParamInitFilterRank; if ((filterRank + outputRank) > shape.Rank()) InvalidArgument("Sum of filter rank (%d) and output rank (%d) of the parameter initializer cannot exceed the Parameter's rank(%d)", filterRank, outputRank, (int)shape.Rank()); } Microsoft::MSR::CNTK::LearnableParameter<ElementType>::InitRandom(*valueMatrix, AsTensorShape(shape), initializerType, randomSeed, (ElementType)scale, filterRank, outputRank, /*initOnCPUOnly=*/true, AsCNTKImplDeviceId(device)); } return value; }
/*static*/ NDArrayViewPtr Variable::CreateValueFromParameterInitializer(const NDShape& shape, const ParameterInitializer& initConfig, const DeviceDescriptor& device) { auto dataType = AsDataType<ElementType>(); auto value = MakeSharedObject<NDArrayView>(dataType, shape, device); auto valueMatrix = value->template GetWritableMatrix<ElementType>(); auto initializerType = initConfig[InitializerTypeAttributeName].Value<std::wstring>(); if (initializerType == Microsoft::MSR::CNTK::ConstantInitializerTypeName) { auto constantInitValue = initConfig[ValueAttributeName].Value<double>(); valueMatrix->SetValue((ElementType)constantInitValue); } else if (initializerType == Microsoft::MSR::CNTK::BilinearInitializerTypeName) { auto kernelWidth = initConfig[KernelWidthAttributeName].Value<size_t>(); auto kernelHeight = initConfig[KernelHeightAttributeName].Value<size_t>(); Microsoft::MSR::CNTK::LearnableParameter<ElementType>::InitBilinear(*valueMatrix, AsTensorShape(shape), kernelWidth, kernelHeight, AsCNTKImplDeviceId(device)); } else { auto randomSeed = (unsigned long)initConfig[RandomSeedAttributeName].Value<size_t>(); auto scale = initConfig[ScaleAttributeName].Value<double>(); int outputRank = DefaultParamInitOutputRank, filterRank = DefaultParamInitFilterRank; if (initializerType != Microsoft::MSR::CNTK::UniformInitializerTypeName) { outputRank = (int)initConfig[OutputRankAttributeName].Value<size_t>(); filterRank = (int)initConfig[FilterRankAttributeName].Value<size_t>(); } Microsoft::MSR::CNTK::LearnableParameter<ElementType>::InitRandom(*valueMatrix, AsTensorShape(shape), initializerType, randomSeed, (ElementType)scale, filterRank, outputRank, false, AsCNTKImplDeviceId(device)); } return value; }
static TensorView<ElementType>* AllocateTensorView(const NDShape& viewShape, CNTK::StorageFormat storageType, const DeviceDescriptor& device) { auto matrixDims = GetMatrixDimensions(viewShape); std::shared_ptr<Matrix<ElementType>> matrix = std::make_shared<Matrix<ElementType>>(matrixDims.first, matrixDims.second, AsCNTKImplDeviceId(device), IsSparseStorageFormat(storageType) ? MatrixType::SPARSE : MatrixType::DENSE, AsCNTKMatrixFormat(storageType)); return new TensorView<ElementType>(matrix, AsTensorShape(viewShape)); }
NDArrayViewPtr NDArrayView::RandomUniform(const NDShape& shape, double rangeStart, double rangeEnd, unsigned long seed, const DeviceDescriptor& device/* = DeviceDescriptor::DefaultDevice()*/) { auto matrixDims = GetMatrixDimensions(shape); auto randomUniformMatrix = std::make_shared<Matrix<ElementType>>(Matrix<ElementType>::RandomUniform(matrixDims.first, matrixDims.second, AsCNTKImplDeviceId(device), (ElementType)rangeStart, (ElementType)rangeEnd, seed)); auto tensorView = new TensorView<ElementType>(randomUniformMatrix, AsTensorShape(shape)); auto view = new NDArrayView(AsDataType<ElementType>(), device, StorageFormat::Dense, shape, false, tensorView); return NDArrayViewPtr(view, [](_ReferenceCounter* ptr) { delete ptr; }); }
static TensorView<ElementType>* AllocateTensorView(const NDShape& viewShape, const DeviceDescriptor& device, void* dataBuffer, size_t bufferSizeInBytes) { if (dataBuffer == nullptr) InvalidArgument("Cannot create a NDArrayView over a null data buffer"); if (bufferSizeInBytes < (viewShape.TotalSize() * sizeof(ElementType))) InvalidArgument("Size of the specified buffer for creating the NDArrayView is smaller than the specified view shape"); auto matrixDims = GetMatrixDimensions(viewShape); std::shared_ptr<Matrix<ElementType>> matrix = std::make_shared<Matrix<ElementType>>(matrixDims.first, matrixDims.second, (ElementType*)dataBuffer, AsCNTKImplDeviceId(device), matrixFlagDontOwnBuffer); return new TensorView<ElementType>(matrix, AsTensorShape(viewShape)); }
/*virtual*/ const std::unordered_map<StreamInformation, MinibatchData>& CompositeMinibatchSource::GetNextMinibatch(size_t minibatchSizeInSequences, size_t minibatchSizeInSamples, size_t numberOfWorkers, size_t workerRank, const DeviceDescriptor& device /*= DeviceDescriptor::UseDefaultDevice()*/) /*override*/ { auto profGetMinibatch = Microsoft::MSR::CNTK::ScopeProfile(Microsoft::MSR::CNTK::profilerEvtMainGetMinibatch); m_minibatchData.clear(); if (!m_epochEndReached) { if (minibatchSizeInSequences != 0) LogicError("GetNextMinibatch: Specifying minibatch size in #sequences is currently unsupported"); if (minibatchSizeInSamples == 0) InvalidArgument("GetNextMinibatch: Requested minibatch size must be > 0."); if (m_prevMinibatchSize == 0) { EpochConfiguration epochConfig; epochConfig.m_numberOfWorkers = numberOfWorkers; epochConfig.m_workerRank = workerRank; epochConfig.m_minibatchSizeInSamples = minibatchSizeInSamples; epochConfig.m_truncationSize = m_truncationLength; epochConfig.m_allowMinibatchesToCrossSweepBoundaries = true; if (m_maxNumSamplesToRead == MinibatchSource::FullDataSweep) { epochConfig.m_totalEpochSizeInSamples = Microsoft::MSR::CNTK::requestDataSize; } else if (m_maxNumSamplesToRead == MinibatchSource::InfinitelyRepeat) { // Setting big value, but not the max in order to avoid bit overflow. epochConfig.m_totalEpochSizeInSamples = std::numeric_limits<size_t>::max() / 2; } else { epochConfig.m_totalEpochSizeInSamples = m_maxNumSamplesToRead; } epochConfig.m_totalEpochSizeInSweeps = m_maxNumSweepsToRead; epochConfig.m_epochIndex = 0; m_matrices.clear(); std::unordered_set<InputStreamDescription> inputs; for (const auto& s : m_streamInfos) { auto inputStreamDescription = GetInputStreamDescription(s, device); inputs.insert(inputStreamDescription); if (s.m_elementType == DataType::Float) { auto iter = std::find_if(m_compositeDataReaderStreamDescs.begin(), m_compositeDataReaderStreamDescs.end(), [s](StreamDescriptionPtr& streamInfo) { return streamInfo->m_id == s.m_id; }); assert(iter != m_compositeDataReaderStreamDescs.end()); m_matrices.AddInput( s.m_name, std::make_shared<Matrix<float>>(0, 0, inputStreamDescription.GetDeviceId(), inputStreamDescription.GetMatrixType(), inputStreamDescription.GetMatrixFormat()), std::make_shared<MBLayout>(), *(*iter)->m_sampleLayout); } else LogicError("GetNextMinibatch: Input of type other than DataType::Float is currently unsupported by the CNTK built-in composite MinibatchSource!"); } m_shim->StartEpoch(epochConfig, inputs); m_prevMinibatchSize = minibatchSizeInSamples; m_workerRank = workerRank; m_numWorkers = numberOfWorkers; } if (minibatchSizeInSamples != m_prevMinibatchSize || m_workerRank != workerRank || m_numWorkers != numberOfWorkers || m_restorePosition != 0) { std::map<std::wstring, int> inputDescriptions; for (const auto& s : m_streamInfos) inputDescriptions[s.m_name] = AsCNTKImplDeviceId(device); ReaderConfiguration newConfig; newConfig.m_numberOfWorkers = numberOfWorkers; newConfig.m_workerRank = workerRank; newConfig.m_minibatchSizeInSamples = minibatchSizeInSamples; newConfig.m_truncationSize = m_truncationLength; newConfig.m_allowMinibatchesToCrossSweepBoundaries = true; if (m_restorePosition != 0) { m_shim->SetCurrentSamplePosition(m_restorePosition); m_restorePosition = 0; } m_shim->SetConfiguration(newConfig, inputDescriptions); m_prevMinibatchSize = minibatchSizeInSamples; m_workerRank = workerRank; m_numWorkers = numberOfWorkers; } auto hasData = m_shim->GetMinibatch(m_matrices); m_epochEndReached = m_shim->IsEndOfEpoch(); if (m_epochEndReached && !hasData) return m_minibatchData; bool hasReachedSweepEnd = m_shim->IsEndOfSweep(); for (const auto& s: m_streamInfos) { auto input = m_matrices.GetInput(s.m_name); auto& currentStreamInfo = s; ValuePtr minibatchValuePtr; if (!hasData) { m_minibatchData[currentStreamInfo] = { nullptr, 0, 0 }; continue; } if (s.m_elementType == DataType::Float) { auto matrix = dynamic_pointer_cast<Matrix<float>>(input.matrix); if (!matrix) LogicError("GetNextMinibatch: Invalid matrix type."); minibatchValuePtr = MakeSharedObject<PackedValue>(s.m_sampleLayout, Axis::DefaultInputVariableDynamicAxes(), matrix, input.pMBLayout, /*readOnly =*/ false); size_t numSamples = input.pMBLayout->GetActualNumSamples(); size_t numSequences = input.pMBLayout->GetNumSequences(); m_minibatchData[currentStreamInfo] = { minibatchValuePtr, numSequences, numSamples, hasReachedSweepEnd }; } else LogicError("GetNextMinibatch: Input of type other than DataType::Float is currently unsupported by the CNTK built-in composite MinibatchSource!"); } } return m_minibatchData; }