Ignore:
Timestamp:
Jan 10, 2017, 2:00:04 PM (2 years ago)
Author:
cameron
Message:

Separate doSegment/final segment processing in pipeline loop; check optional NoTerminateAttribute?

File:
1 edited

Legend:

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

    r5251 r5252  
    1818
    1919
    20 static void createStreamBufferMap(BufferMap bufferMap, std::vector<KernelBuilder *> kernels) {
     20static void createStreamBufferMap(BufferMap & bufferMap, std::vector<KernelBuilder *> kernels) {
    2121    for (auto k: kernels) {
    2222        auto outputSets = k->getStreamSetOutputBuffers();
     
    3535}
    3636
     37static Value * getSegmentBlocks(BufferMap & bufferMap, KernelBuilder * kernel) {
     38    IDISA::IDISA_Builder * iBuilder = kernel->getBuilder();
     39    std::cerr << "getSegmentBlocks\n";
     40
     41    KernelBuilder * sourceKernel;
     42
     43    unsigned outputIndex;
     44    auto inputs = kernel->getStreamSetInputBuffers();
     45    if (inputs.empty()) return iBuilder->getSize(codegen::SegmentSize * iBuilder->getStride() / iBuilder->getBitBlockWidth());
     46    std::string inputSetName = kernel->getStreamInputs()[0].name;
     47    std::cerr << "inputSetName = " << inputSetName << "\n";
     48    auto f = bufferMap.find(inputs[0]);
     49    assert(f != bufferMap.end()  && "bufferMap failure");
     50    std::tie(sourceKernel, outputIndex) = f->second;
     51    std::cerr << "outputIndex = " << outputIndex << "\n";
     52    Value * produced = sourceKernel->getProducedItemCount(sourceKernel->getInstance(), sourceKernel->getStreamOutputs()[outputIndex].name);
     53    iBuilder->CallPrintInt("produced", produced);
     54    Value * processed = kernel->getProcessedItemCount(kernel->getInstance(), inputSetName);
     55    iBuilder->CallPrintInt("processed", processed);
     56    Value * itemsToDo = iBuilder->CreateSub(produced, processed);
     57    return iBuilder->CreateUDiv(itemsToDo, iBuilder->getSize(iBuilder->getStride()));
     58}
     59                                   
     60
    3761
    3862Function * generateSegmentParallelPipelineThreadFunction(std::string name, IDISA::IDISA_Builder * iBuilder, std::vector<KernelBuilder *> kernels, Type * sharedStructType, int id) {
     
    215239void generatePipelineLoop(IDISA::IDISA_Builder * iBuilder, std::vector<KernelBuilder *> kernels) {
    216240   
     241   
     242    for (auto k : kernels) k->createInstance();
     243    //BufferMap bufferMap;
     244    //createStreamBufferMap(bufferMap, kernels);
     245   
    217246    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
    218247    Function * main = entryBlock->getParent();
    219        
    220     const unsigned segmentSize = codegen::SegmentSize;
    221     Type * const size_ty = iBuilder->getSizeTy();
    222 
    223     // Create the basic blocks for the loop.
    224     BasicBlock * segmentBlock = BasicBlock::Create(iBuilder->getContext(), "segmentLoop", main, 0);
     248
     249    // Create the basic blocks. 
     250    BasicBlock * segmentLoop = BasicBlock::Create(iBuilder->getContext(), "segmentLoop", main, 0);
    225251    BasicBlock * exitBlock = BasicBlock::Create(iBuilder->getContext(), "exitBlock", main, 0);
    226     for (auto k : kernels) k->createInstance();
    227     iBuilder->CreateBr(segmentBlock);
    228     iBuilder->SetInsertPoint(segmentBlock);
    229     Constant * segBlocks = ConstantInt::get(size_ty, segmentSize * iBuilder->getStride() / iBuilder->getBitBlockWidth());
    230     for (unsigned i = 0; i < kernels.size(); i++) {
     252    // We create vectors of loop body and final segment blocks indexed by kernel.
     253    std::vector<BasicBlock *> loopBodyBlocks;
     254    std::vector<BasicBlock *> finalSegmentBlocks;
     255
     256    loopBodyBlocks.push_back(segmentLoop);
     257    finalSegmentBlocks.push_back(nullptr); 
     258   
     259    for (unsigned i = 1; i < kernels.size(); i++) {
     260        if (kernels[i-1]->hasNoTerminateAttribute()) {
     261            // Previous kernel cannot terminate.   Continue with the previous blocks;
     262            loopBodyBlocks.push_back(loopBodyBlocks.back());
     263            finalSegmentBlocks.push_back(finalSegmentBlocks.back());
     264        }
     265        else {
     266            loopBodyBlocks.push_back(BasicBlock::Create(iBuilder->getContext(), "do_" + kernels[i]->getName(), main, 0));
     267            finalSegmentBlocks.push_back(BasicBlock::Create(iBuilder->getContext(), "finish_" + kernels[i]->getName(), main, 0));
     268        }
     269    }
     270    loopBodyBlocks.push_back(segmentLoop); // If the last kernel does not terminate, loop back.
     271    finalSegmentBlocks.push_back(exitBlock); // If the last kernel does terminate, we're done.
     272   
     273    iBuilder->CreateBr(segmentLoop);
     274    Constant * segBlocks = iBuilder->getSize(codegen::SegmentSize * iBuilder->getStride() / iBuilder->getBitBlockWidth());
     275    for (unsigned i = 0; i < kernels.size(); i++) {
     276        iBuilder->SetInsertPoint(loopBodyBlocks[i]);
     277        //Value * segBlocks = getSegmentBlocks(bufferMap, kernels[i]);
     278        Value * segNo = kernels[i]->acquireLogicalSegmentNo(kernels[i]->getInstance());
    231279        kernels[i]->createDoSegmentCall(kernels[i]->getInstance(), segBlocks);
    232         Value * segNo = kernels[i]->acquireLogicalSegmentNo(kernels[i]->getInstance());
    233         kernels[i]->releaseLogicalSegmentNo(kernels[i]->getInstance(), iBuilder->CreateAdd(segNo, iBuilder->getSize(1)));
    234     }
    235     Value * endSignal = kernels.back()->getTerminationSignal(kernels.back()->getInstance());
    236     iBuilder->CreateCondBr(endSignal, exitBlock, segmentBlock);
     280        if (kernels[i]->hasNoTerminateAttribute()) {
     281            kernels[i]->releaseLogicalSegmentNo(kernels[i]->getInstance(), iBuilder->CreateAdd(segNo, iBuilder->getSize(1)));
     282            if (i == kernels.size() - 1) {
     283                iBuilder->CreateBr(segmentLoop);
     284            }
     285        }
     286        else {
     287            Value * terminated = kernels[i]->getTerminationSignal(kernels[i]->getInstance());
     288            kernels[i]->releaseLogicalSegmentNo(kernels[i]->getInstance(), iBuilder->CreateAdd(segNo, iBuilder->getSize(1)));
     289            iBuilder->CreateCondBr(terminated, finalSegmentBlocks[i+1], loopBodyBlocks[i+1]);
     290        }
     291        if (finalSegmentBlocks[i] != nullptr) {
     292            iBuilder->SetInsertPoint(finalSegmentBlocks[i]);
     293            Value * segNo = kernels[i]->acquireLogicalSegmentNo(kernels[i]->getInstance());
     294            kernels[i]->createDoSegmentCall(kernels[i]->getInstance(), segBlocks);
     295            kernels[i]->releaseLogicalSegmentNo(kernels[i]->getInstance(), iBuilder->CreateAdd(segNo, iBuilder->getSize(1)));
     296            if (finalSegmentBlocks[i] != finalSegmentBlocks[i+1]) {
     297                iBuilder->CreateBr(finalSegmentBlocks[i+1]);
     298            }
     299        }
     300    }
    237301    iBuilder->SetInsertPoint(exitBlock);
    238 
    239 }
     302}
     303
     304
     305
     306
     307
     308
     309
     310
     311
     312
     313
     314
     315
     316
     317
     318
     319
     320
     321
     322
Note: See TracChangeset for help on using the changeset viewer.