Ignore:
Timestamp:
Aug 29, 2016, 1:53:08 PM (3 years ago)
Author:
lindanl
Message:

Add pipeline parallel strategy to the framework.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/grep_engine.cpp

    r5134 r5135  
    2424#include <llvm/Support/Debug.h>
    2525#include <llvm/IR/Verifier.h>
     26#include <llvm/IR/TypeBuilder.h>
    2627#include <UCD/UnicodeNameData.h>
    2728
     
    7879static cl::opt<bool> ShowLineNumbers("n", cl::desc("Show the line number with each matching line."), cl::cat(bGrepOutputOptions));
    7980static cl::alias ShowLineNumbersLong("line-number", cl::desc("Alias for -n"), cl::aliasopt(ShowLineNumbers));
     81
     82static cl::opt<bool> pipelineParallel("enable-pipeline-parallel", cl::desc("Enable multithreading with pipeline parallelism."), cl::cat(bGrepOutputOptions));
    8083
    8184
     
    117120
    118121using namespace parabix;
    119 
     122/*
    120123void GrepEngine::grepCodeGen(std::string moduleName, re::RE * re_ast, bool CountOnly, bool UTF_16, bool isNameExpression) {
    121124    isUTF_16 = UTF_16;
     
    213216
    214217}
    215 
    216 
     218*/
     219void GrepEngine::grepCodeGen(std::string moduleName, re::RE * re_ast, bool CountOnly, bool UTF_16, bool isNameExpression) {
     220    isUTF_16 = UTF_16;
     221    Module * M = new Module(moduleName, getGlobalContext());
     222   
     223    IDISA::IDISA_Builder * iBuilder = IDISA::GetIDISA_Builder(M);
     224
     225    const unsigned segmentSize = codegen::SegmentSize;
     226    const unsigned bufferSegments = codegen::BufferSegments;
     227
     228    Encoding::Type type;
     229    type = UTF_16 ? Encoding::Type::UTF_16 : Encoding::Type::UTF_8;
     230    unsigned bits;
     231    bits = UTF_16 ? 16 : 8;
     232
     233    Encoding encoding(type, bits);
     234    mIsNameExpression = isNameExpression;
     235
     236    Type * const int64ty = iBuilder->getInt64Ty();
     237    Type * const int32ty = iBuilder->getInt32Ty();
     238    Type * const size_ty = iBuilder->getSizeTy();
     239    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
     240    Type * const voidTy = Type::getVoidTy(M->getContext());   
     241    Type * const voidPtrTy = TypeBuilder<void *, false>::get(M->getContext());
     242    Type * const inputType = PointerType::get(ArrayType::get(ArrayType::get(iBuilder->getBitBlockType(), (UTF_16 ? 16 : 8)), 1), 0);
     243    Type * const resultTy = CountOnly ? size_ty : iBuilder->getVoidTy();
     244    Function * const mainFn = cast<Function>(M->getOrInsertFunction("Main", resultTy, inputType, size_ty, size_ty, nullptr));
     245    mainFn->setCallingConv(CallingConv::C);
     246    iBuilder->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", mainFn, 0));
     247    Function::arg_iterator args = mainFn->arg_begin();
     248   
     249    Value * const inputStream = &*(args++);
     250    inputStream->setName("input");
     251    Value * const fileSize = &*(args++);
     252    fileSize->setName("fileSize");
     253    Value * const fileIdx = &*(args++);
     254    fileIdx->setName("fileIdx");
     255       
     256    ExternalUnboundedBuffer ByteStream(iBuilder, StreamSetType(1, i8));
     257    CircularBuffer BasisBits(iBuilder, StreamSetType(8, i1), segmentSize * bufferSegments);
     258
     259    kernel::s2pKernel  s2pk(iBuilder);
     260    s2pk.generateKernel({&ByteStream}, {&BasisBits});
     261
     262    re_ast = re::regular_expression_passes(encoding, re_ast);   
     263    pablo::PabloFunction * function = re::re2pablo_compiler(encoding, re_ast, CountOnly);
     264    pablo_function_passes(function);
     265
     266    ByteStream.setStreamSetBuffer(inputStream);
     267    BasisBits.allocateBuffer();
     268
     269    Value * producerPtr = ByteStream.getProducerPosPtr(ByteStream.getStreamSetStructPtr());
     270    iBuilder->CreateAlignedStore(fileSize, producerPtr, 8)->setOrdering(Release);
     271
     272    Value * s2pInstance = s2pk.createInstance({});
     273 
     274    Type * pthreadTy = int64ty; //Pthread Type for 64-bit machine.
     275    FunctionType * funVoidPtrVoidTy = FunctionType::get(voidTy, int8PtrTy, false);   
     276   
     277    Function * pthreadCreateFunc = cast<Function>(M->getOrInsertFunction("pthread_create",
     278                                        int32ty,
     279                                        pthreadTy->getPointerTo(),
     280                                        voidPtrTy,
     281                                        static_cast<Type *>(funVoidPtrVoidTy)->getPointerTo(),
     282                                        voidPtrTy, nullptr));
     283    pthreadCreateFunc->setCallingConv(llvm::CallingConv::C);
     284    Function * pthreadJoinFunc = cast<Function>(M->getOrInsertFunction("pthread_join",
     285                                        int32ty,
     286                                        pthreadTy,
     287                                        PointerType::get(int8PtrTy, 0), nullptr));
     288    pthreadJoinFunc->setCallingConv(llvm::CallingConv::C);
     289
     290    Function * pthreadExitFunc = cast<Function>(M->getOrInsertFunction("pthread_exit",
     291                                        voidTy,
     292                                        voidPtrTy, nullptr));
     293    pthreadExitFunc->addFnAttr(llvm::Attribute::NoReturn);
     294    pthreadExitFunc->setCallingConv(llvm::CallingConv::C);
     295   
     296    // Type * const pthreadsTy = ArrayType::get(pthreadTy, 3);
     297    // AllocaInst * const pthreads = iBuilder->CreateAlloca(pthreadsTy);
     298    // Value * pthreadsPtr1 = iBuilder->CreateGEP(pthreads, {iBuilder->getInt32(0), iBuilder->getInt32(0)});
     299    // Value * pthreadsPtr2 = iBuilder->CreateGEP(pthreads, {iBuilder->getInt32(0), iBuilder->getInt32(1)});
     300    // Value * pthreadsPtr3 = iBuilder->CreateGEP(pthreads, {iBuilder->getInt32(0), iBuilder->getInt32(2)});
     301    // Value * nullVal = Constant::getNullValue(voidPtrTy);
     302    // AllocaInst * const status = iBuilder->CreateAlloca(int8PtrTy);
     303
     304    if (CountOnly) {
     305        pablo::PabloKernel  icgrepK(iBuilder, "icgrep", function, {"matchedLineCount"});
     306        icgrepK.generateKernel({&BasisBits}, {});       
     307        Value * icgrepInstance = icgrepK.createInstance({});
     308
     309        if (pipelineParallel){
     310            // const auto ip = iBuilder->saveIP();
     311            // Function * s2p_func = s2pk.generateThreadFunction("s2p");
     312            // Function * icgrep_func = icgrepK.generateThreadFunction("icgrep");
     313            // iBuilder->restoreIP(ip);
     314
     315            // iBuilder->CreateCall(pthreadCreateFunc, std::vector<Value *>({pthreadsPtr1, nullVal, s2p_func, iBuilder->CreateBitCast(s2pInstance, int8PtrTy)}));
     316            // iBuilder->CreateCall(pthreadCreateFunc, std::vector<Value *>({pthreadsPtr2, nullVal, icgrep_func, iBuilder->CreateBitCast(icgrepInstance, int8PtrTy)}));
     317         
     318            // Value * threadID1 = iBuilder->CreateLoad(pthreadsPtr1);
     319            // Value * threadID2 = iBuilder->CreateLoad(pthreadsPtr2);
     320
     321            // iBuilder->CreateCall(pthreadJoinFunc, std::vector<Value *>({threadID1, status}));
     322            // iBuilder->CreateCall(pthreadJoinFunc, std::vector<Value *>({threadID2, status}));
     323            generatePipelineParallel(iBuilder, {&s2pk, &icgrepK}, {s2pInstance, icgrepInstance});
     324
     325        }
     326        else{
     327            generatePipelineLoop(iBuilder, {&s2pk, &icgrepK}, {s2pInstance, icgrepInstance}, fileSize);
     328
     329        }
     330       
     331        Value * matchCount = icgrepK.createGetAccumulatorCall(icgrepInstance, "matchedLineCount");
     332        iBuilder->CreateRet(matchCount);
     333
     334    }
     335    else {
     336        CircularBuffer MatchResults(iBuilder, StreamSetType(2, i1), segmentSize * bufferSegments);
     337        MatchResults.allocateBuffer();
     338
     339        pablo::PabloKernel  icgrepK(iBuilder, "icgrep", function, {});
     340        icgrepK.generateKernel({&BasisBits},  {&MatchResults});
     341        Value * icgrepInstance = icgrepK.createInstance({});
     342
     343        kernel::scanMatchKernel scanMatchK(iBuilder, mIsNameExpression);
     344        scanMatchK.generateKernel({&MatchResults}, {});               
     345        Value * scanMatchInstance = scanMatchK.createInstance({iBuilder->CreateBitCast(inputStream, int8PtrTy), fileSize, fileIdx});
     346
     347        if (pipelineParallel){
     348            generatePipelineParallel(iBuilder, {&s2pk, &icgrepK, &scanMatchK}, {s2pInstance, icgrepInstance, scanMatchInstance});
     349
     350        }
     351        else{
     352            generatePipelineLoop(iBuilder, {&s2pk, &icgrepK, &scanMatchK}, {s2pInstance, icgrepInstance, scanMatchInstance}, fileSize);
     353        }
     354        // const auto ip = iBuilder->saveIP();
     355        // Function * s2p_func = s2pk.generateThreadFunction("s2p");
     356        // Function * icgrep_func = icgrepK.generateThreadFunction("icgrep");   
     357        // Function * scan_func = scanMatchK.generateThreadFunction("scanMatch");
     358        // iBuilder->restoreIP(ip);
     359       
     360        // iBuilder->CreateCall(pthreadCreateFunc, std::vector<Value *>({pthreadsPtr1, nullVal, s2p_func, iBuilder->CreateBitCast(s2pInstance, int8PtrTy)}));
     361        // iBuilder->CreateCall(pthreadCreateFunc, std::vector<Value *>({pthreadsPtr2, nullVal, icgrep_func, iBuilder->CreateBitCast(icgrepInstance, int8PtrTy)}));
     362        // iBuilder->CreateCall(pthreadCreateFunc, std::vector<Value *>({pthreadsPtr3, nullVal, scan_func, iBuilder->CreateBitCast(scanMatchInstance, int8PtrTy)}));
     363
     364        // Value * threadID1 = iBuilder->CreateLoad(pthreadsPtr1);
     365        // Value * threadID2 = iBuilder->CreateLoad(pthreadsPtr2);
     366        // Value * threadID3 = iBuilder->CreateLoad(pthreadsPtr3);
     367     
     368        // iBuilder->CreateCall(pthreadJoinFunc, std::vector<Value *>({threadID1, status}));
     369        // iBuilder->CreateCall(pthreadJoinFunc, std::vector<Value *>({threadID2, status}));
     370        // iBuilder->CreateCall(pthreadJoinFunc, std::vector<Value *>({threadID3, status}));
     371        iBuilder->CreateRetVoid();
     372
     373    }
     374     
     375    mEngine = JIT_to_ExecutionEngine(M);
     376    ApplyObjectCache(mEngine);
     377    icgrep_Linking(M, mEngine);
     378
     379#ifndef NDEBUG
     380    verifyModule(*M, &dbgs());
     381#endif
     382
     383    mEngine->finalizeObject();
     384    delete iBuilder;
     385   
     386    if (CountOnly) {
     387        mGrepFunction_CountOnly = reinterpret_cast<GrepFunctionType_CountOnly>(mEngine->getPointerToFunction(mainFn));
     388    } else {
     389        mGrepFunction = reinterpret_cast<GrepFunctionType>(mEngine->getPointerToFunction(mainFn));
     390    }
     391
     392}
    217393
    218394re::CC *  GrepEngine::grepCodepoints() {
Note: See TracChangeset for help on using the changeset viewer.