void MultiplexLayer::forward(PassType passType) { Layer::forward(passType); IVectorPtr copyIds = getInput(0).ids; MatrixPtr inV1 = getInputValue(1); CHECK_EQ(copyIds->getSize(), inV1->getHeight()); for (size_t i = 2; i < inputLayers_.size(); i++) { CHECK_EQ(inV1->getHeight(), getInputValue(i)->getHeight()); CHECK_EQ(inV1->getWidth(), getInputValue(i)->getWidth()); } calculateCopySchedule(copyIds, inputLayers_.size() - 1); { REGISTER_TIMER_INFO("FwResetTimer", getName().c_str()); reserveOutput(inV1->getHeight(), inV1->getWidth()); } MatrixPtr outV = getOutputValue(); { REGISTER_TIMER_INFO("FwLMultplexingTimer", getName().c_str()); AsyncGpuBlock block; for (const CopyInfo& info : copySchedule_) { outV->subMatrix(info.startIdx, info.length, tmpDest_) ->copyFrom(*getInputValue(info.copyIdx + 1) ->subMatrix(info.startIdx, info.length, tmpSrc_)); } } /* activation */ { REGISTER_TIMER_INFO("FwAtvTimer", getName().c_str()); forwardActivation(); } }
TEST(Argument, poolSequenceWithStride) { Argument input, output; ICpuGpuVector::resizeOrCreate(input.sequenceStartPositions, 5, false); int* inStart = input.sequenceStartPositions->getMutableData(false); inStart[0] = 0; inStart[1] = 9; inStart[2] = 14; inStart[3] = 17; inStart[4] = 30; int strideResult[] = {0, 5, 9, 14, 17, 22, 27, 30}; int strideResultReversed[] = {0, 4, 9, 14, 17, 20, 25, 30}; for (auto reversed : {false, true}) { IVectorPtr stridePositions; output.poolSequenceWithStride( input, 5 /* stride */, &stridePositions, reversed); const int* outStart = output.sequenceStartPositions->getData(false); CHECK_EQ(outStart[0], 0); CHECK_EQ(outStart[1], 2); CHECK_EQ(outStart[2], 3); CHECK_EQ(outStart[3], 4); CHECK_EQ(outStart[4], 7); CHECK_EQ(stridePositions->getSize(), 8); auto result = reversed ? strideResultReversed : strideResult; for (int i = 0; i < 8; i++) { CHECK_EQ(stridePositions->getData()[i], result[i]); } } }
void SparsePrefetchRowCpuMatrix::addRows(IVectorPtr ids) { std::vector<unsigned int>& localIndices = indexDictHandle_->localIndices; size_t numSamples = ids->getSize(); int* index = ids->getData(); for (size_t i = 0; i < numSamples; ++i) { if (index[i] == -1) continue; unsigned int id = (unsigned int)index[i]; CHECK_LT(id, this->getHeight()) << "id:" << id << "Height:" << this->getHeight() << "sparse id value exceeds the max input dimension, " << "it could be caused invalid input data samples"; localIndices.push_back(id); } }
void generateMDimSequenceData(const IVectorPtr& sequenceStartPositions, IVectorPtr& cpuSequenceDims) { /* generate sequences with 2 dims */ int numSeqs = sequenceStartPositions->getSize() - 1; int numDims = 2; cpuSequenceDims = IVector::create(numSeqs * numDims, /* useGpu= */ false); int* bufStarts = sequenceStartPositions->getData(); int* bufDims = cpuSequenceDims->getData(); for (int i = 0; i < numSeqs; i++) { int len = bufStarts[i + 1] - bufStarts[i]; /* get width and height randomly */ std::vector<int> dimVec; for (int j = 0; j < len; j++) { if (len % (j + 1) == 0) { dimVec.push_back(1); } } int idx = rand() % dimVec.size(); // NOLINT use rand_r bufDims[i * numDims] = dimVec[idx]; bufDims[i * numDims + 1] = len / dimVec[idx]; } }
void MultiplexLayer::calculateCopySchedule(const IVectorPtr& copyIds, size_t numIns) { copySchedule_.clear(); CopyInfo prevCopyInfo(0, 0, -1); for (size_t i = 0; i < copyIds->getSize(); i++) { int copyId = copyIds->getElement(i); CHECK_GE(copyId, 0); CHECK_LT(copyId, int(numIns)); // copy same input layer with prevous and will copy consecutive. if (copyId == prevCopyInfo.copyIdx) { ++prevCopyInfo.length; } else { if (prevCopyInfo.copyIdx != -1) { copySchedule_.emplace_back(prevCopyInfo); } prevCopyInfo.startIdx = i; prevCopyInfo.length = 1; prevCopyInfo.copyIdx = copyId; } } if (prevCopyInfo.copyIdx != -1) { copySchedule_.emplace_back(prevCopyInfo); } }
void checkVectorEqual(const IVectorPtr& a, const IVectorPtr& b) { EXPECT_EQ(a->getSize(), b->getSize()); for (size_t r = 0; r < a->getSize(); ++r) { EXPECT_FLOAT_EQ(a->get(r), b->get(r)); } }