Ignore:
Timestamp:
Mar 31, 2017, 3:05:41 PM (2 years ago)
Author:
nmedfort
Message:

Replaced stdin input stream with mmap'ed buffer and aligned each read call to the page size.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/kernels/stdin_kernel.cpp

    r5379 r5386  
    1010using namespace llvm;
    1111
     12inline static size_t round_up_to_nearest(const size_t x, const size_t y) {
     13    return (((x - 1) | (y - 1)) + 1);
     14}
     15
    1216namespace kernel {
    1317
    1418void StdInKernel::generateDoSegmentMethod(Value * /* doFinal */, const std::vector<Value *> & /* producerPos */) {
    1519
    16     BasicBlock * setTermination = CreateBasicBlock("setTermination");
    17     BasicBlock * stdInExit = CreateBasicBlock("stdInExit");
    18     ConstantInt * segmentBytes = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
    19     ConstantInt * segmentBytes2 = iBuilder->getSize(2 * mSegmentBlocks * iBuilder->getBitBlockWidth());
    20     // on the first segment, we buffer twice the data to ensure the ScanMatch kernel can safely check for a non-LF line break
     20    BasicBlock * const entryBlock = iBuilder->GetInsertBlock();
     21    BasicBlock * const readBlock = CreateBasicBlock("ReadMoreData");
     22    BasicBlock * const setTermination = CreateBasicBlock("SetTermination");
     23    BasicBlock * const stdInExit = CreateBasicBlock("StdInExit");
     24
     25    ConstantInt * const segmentSize = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
     26    Value * bufferedSize = getScalarField("BufferedSize");
    2127    Value * const itemsAlreadyRead = getProducedItemCount("codeUnitBuffer");
    22     Value * const bytesToRead = iBuilder->CreateSelect(iBuilder->CreateICmpEQ(itemsAlreadyRead, iBuilder->getSize(0)), segmentBytes2, segmentBytes);
     28    Value * const bytesAlreadyRead = iBuilder->CreateMul(itemsAlreadyRead, iBuilder->getSize(mCodeUnitWidth / 8));
     29    Value * unreadSize = iBuilder->CreateSub(bufferedSize, bytesAlreadyRead);
     30    Value * const exaustedBuffer = iBuilder->CreateICmpULT(unreadSize, segmentSize);
     31    iBuilder->CreateUnlikelyCondBr(exaustedBuffer, readBlock, stdInExit);
     32
     33    iBuilder->SetInsertPoint(readBlock);
     34    // how many pages are required to have enough data for the segment plus one overflow block?
     35    const auto PageAlignedSegmentSize = round_up_to_nearest((mSegmentBlocks + 1) * iBuilder->getBitBlockWidth() * (mCodeUnitWidth / 8), getpagesize());
     36    ConstantInt * const bytesToRead = iBuilder->getSize(PageAlignedSegmentSize);
    2337    reserveBytes("codeUnitBuffer", bytesToRead);
    24     Value * const bytePtr = iBuilder->CreatePointerCast(getOutputStreamBlockPtr("codeUnitBuffer", iBuilder->getInt32(0)), iBuilder->getInt8PtrTy());
     38    BasicBlock * const readExit = iBuilder->GetInsertBlock();
     39
     40    Value * const ptr = getRawOutputPointer("codeUnitBuffer", iBuilder->getInt32(0), bufferedSize);
     41    Value * const bytePtr = iBuilder->CreatePointerCast(ptr, iBuilder->getInt8PtrTy());
    2542    Value * const bytesRead = iBuilder->CreateReadCall(iBuilder->getInt32(STDIN_FILENO), bytePtr, bytesToRead);
    26     Value * const itemsRead = iBuilder->CreateAdd(itemsAlreadyRead, iBuilder->CreateUDiv(bytesRead, iBuilder->getSize(mCodeUnitWidth / 8)));
    27     setProducedItemCount("codeUnitBuffer", itemsRead);
    28     iBuilder->CreateCondBr(iBuilder->CreateICmpEQ(bytesRead, ConstantInt::getNullValue(bytesRead->getType())), setTermination, stdInExit);
     43
     44    unreadSize = iBuilder->CreateAdd(unreadSize, bytesRead);
     45    bufferedSize = iBuilder->CreateAdd(bufferedSize, bytesRead);
     46    setScalarField("BufferedSize", bufferedSize);
     47    iBuilder->CreateUnlikelyCondBr(iBuilder->CreateICmpULT(unreadSize, segmentSize), setTermination, stdInExit);
     48
    2949    iBuilder->SetInsertPoint(setTermination);
     50    Value * const itemsRemaining = iBuilder->CreateUDiv(unreadSize, iBuilder->getSize(mCodeUnitWidth / 8));
    3051    setTerminationSignal();
    3152    iBuilder->CreateBr(stdInExit);
     53
    3254    stdInExit->moveAfter(iBuilder->GetInsertBlock());
     55
    3356    iBuilder->SetInsertPoint(stdInExit);
     57    PHINode * const produced = iBuilder->CreatePHI(itemsAlreadyRead->getType(), 3);
     58
     59    produced->addIncoming(segmentSize, entryBlock);
     60    produced->addIncoming(segmentSize, readExit);
     61    produced->addIncoming(itemsRemaining, setTermination);
     62    Value * const itemsRead = iBuilder->CreateAdd(itemsAlreadyRead, produced);
     63
     64    setProducedItemCount("codeUnitBuffer", itemsRead);
    3465}
    3566
    3667StdInKernel::StdInKernel(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
    37 : SegmentOrientedKernel(iBuilder, "stdin_source", {}, {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {})
     68: SegmentOrientedKernel(iBuilder, "stdin_source", {}, {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {Binding{iBuilder->getSizeTy(), "BufferedSize"}})
    3869, mSegmentBlocks(blocksPerSegment)
    3970, mCodeUnitWidth(codeUnitWidth) {
Note: See TracChangeset for help on using the changeset viewer.