source: icGREP/icgrep-devel/icgrep/editd/editd.cpp @ 5418

Last change on this file since 5418 was 5418, checked in by nmedfort, 2 years ago

Removed non-functional CUDA code from icgrep and consolidated grep and multigrep mode into a single function; allowed segment parallel pipeline to utilize process as its initial thread; modified MMapSourceKernel to map and perform mmap directly and advise the OS to drop consumed data streams.

  • Property svn:executable set to *
File size: 25.5 KB
RevLine 
[5172]1/*
2 *  Copyright (c) 2015 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include <string>
8#include <iostream>
9#include <fstream>
[5402]10#include <kernels/toolchain.h>
[5172]11#include <pablo/pablo_toolchain.h>
12#include <llvm/IR/Function.h>
13#include <llvm/IR/Module.h>
14#include <llvm/ExecutionEngine/ExecutionEngine.h>
15#include "llvm/Linker/Linker.h"
16#include <llvm/Support/CommandLine.h>
17#include <cc/cc_compiler.h>
18#include <pablo/pablo_compiler.h>
19#include <pablo/pablo_kernel.h>
[5238]20#include <IR_Gen/idisa_builder.h>
21#include <IR_Gen/idisa_target.h>
[5172]22#include <kernels/streamset.h>
[5254]23#include <kernels/mmap_kernel.h>
[5418]24#include <kernels/stdin_kernel.h>
[5172]25#include <kernels/s2p_kernel.h>
26#include <editd/editdscan_kernel.h>
27#include <kernels/pipeline.h>
28#include <editd/pattern_compiler.h>
[5418]29#include <sys/stat.h>
30#include <fcntl.h>
[5244]31#include <mutex>
[5212]32#ifdef CUDA_ENABLED
33#include <editd/EditdCudaDriver.h>
34#include <editd/editd_gpu_kernel.h>
35#endif
36
[5267]37using namespace llvm;
38
[5172]39static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<regex> <input file ...>"), cl::OneOrMore);
40
41static cl::list<std::string> pattVector("e", cl::desc("pattern"), cl::ZeroOrMore);
42static cl::opt<std::string> PatternFilename("f", cl::desc("Take patterns (one per line) from a file"), cl::value_desc("regex file"), cl::init(""));
43
44static cl::opt<bool> CaseInsensitive("i", cl::desc("Ignore case distinctions in the pattern and the file."));
45
46static cl::opt<int> editDistance("edit-dist", cl::desc("Edit Distance Value"), cl::init(2));
47static cl::opt<int> optPosition("opt-pos", cl::desc("Optimize position"), cl::init(8));
48static cl::opt<int> stepSize("step-size", cl::desc("Step Size"), cl::init(3));
[5212]49static cl::opt<int> prefixLen("prefix", cl::desc("Prefix length"), cl::init(4));
[5223]50static cl::opt<bool> ShowPositions("display", cl::desc("Display the match positions."), cl::init(false));
[5172]51
[5244]52static cl::opt<int> Threads("threads", cl::desc("Total number of threads."), cl::init(1));
53
[5172]54using namespace kernel;
55using namespace pablo;
[5260]56using namespace parabix;
[5172]57
[5260]58const static std::string IRFilename = "editd.ll";
59const static std::string PTXFilename = "editd.ptx";
[5212]60
[5173]61struct matchPosition
62{
63    size_t pos;
64    size_t dist;
65};
66
67std::vector<struct matchPosition> matchList;
[5212]68std::vector<std::vector<std::string>> pattGroups;
[5173]69
70void run_second_filter(int total_len, int pattern_segs, float errRate){
71   
[5240]72    if(matchList.empty()) return;
[5173]73
[5212]74    //remove the duplicates
75    bool cleared = true;
76    while(cleared){
77        cleared = false;
78        for (unsigned i=0; i<matchList.size()-1; i++){
79            if(matchList[i].pos == matchList[i+1].pos && matchList[i].dist == matchList[i+1].dist){
80                matchList.erase(matchList.begin() + i);
81                cleared = true;
82            }
83        }
84    }
85
[5173]86    //Sort match position
87    bool exchanged = true;
88    while(exchanged){
89        exchanged = false;
[5177]90        for (unsigned i=0; i<matchList.size()-1; i++){
[5173]91            if(matchList[i].pos > matchList[i+1].pos){
92                size_t tmp_pos = matchList[i].pos;
93                size_t tmp_dist = matchList[i].dist;
94                matchList[i].pos = matchList[i+1].pos;
95                matchList[i].dist = matchList[i+1].dist;
96                matchList[i+1].pos = tmp_pos;
97                matchList[i+1].dist = tmp_dist;
98                exchanged = true;
99            }
100        }
101    }
102
[5223]103    std::cout << "pattern_segs = " << pattern_segs << ", total_len = " << total_len << std::endl;
[5173]104
105    int v = pattern_segs * (editDistance+1) - total_len * errRate;
106
107    int startPos = matchList[0].pos;
108    int sum = matchList[0].dist;
109    int curIdx = 0;
[5177]110    unsigned i = 0;
[5173]111    int count = 0;
112    while (i < matchList.size()){
113        if(matchList[i].pos - startPos < total_len * (errRate+1)){
114            sum += matchList[i].dist;
115            i++;
116        }
117        else{
118            if(sum > v) count++;
119            sum -= matchList[curIdx].dist;
120            curIdx++;
121            startPos = matchList[curIdx].pos;
122        }
123    }
[5223]124
[5173]125    std::cout << "total candidate from the first filter is " << matchList.size() << std::endl;
126    std::cout << "total candidate from the second filter is " << count << std::endl;
127}
128
[5172]129extern "C" {
[5244]130std::mutex store_mutex;
[5172]131void wrapped_report_pos(size_t match_pos, int dist) {
[5173]132        struct matchPosition curMatch;
133        curMatch.pos = match_pos;
134        curMatch.dist = dist;
[5244]135
136        store_mutex.lock();
[5173]137        matchList.push_back(curMatch);
[5223]138        if(ShowPositions)
139            std::cout << "pos: " << match_pos << ", dist:" << dist << "\n";
[5244]140        store_mutex.unlock();
[5172]141    }
142
143}
144
145void icgrep_Linking(Module * m, ExecutionEngine * e) {
146    Module::FunctionListType & fns = m->getFunctionList();
147    for (Module::FunctionListType::iterator it = fns.begin(), it_end = fns.end(); it != it_end; ++it) {
148        std::string fnName = it->getName().str();
149        if (fnName == "wrapped_report_pos") {
150            e->addGlobalMapping(cast<GlobalValue>(it), (void *)&wrapped_report_pos);
151        }
152    }
153}
154
[5173]155void get_editd_pattern(int & pattern_segs, int & total_len) {
[5172]156 
157    if (PatternFilename != "") {
158        std::ifstream pattFile(PatternFilename.c_str());
159        std::string r;
160        if (pattFile.is_open()) {
161            while (std::getline(pattFile, r)) {
162                pattVector.push_back(r);
[5173]163                pattern_segs ++; 
164                total_len += r.size(); 
[5172]165            }
[5212]166            std::sort(pattVector.begin(), pattVector.end());
167            unsigned i = 0;
168            while(i < pattVector.size()){
169                std::vector<std::string> pattGroup;
170                std::string prefix = pattVector[i].substr(0, prefixLen);
171                while(i < pattVector.size() && pattVector[i].substr(0, prefixLen) == prefix){
172                    pattGroup.push_back(pattVector[i]);
173                    i++;
174                } 
175                pattGroups.push_back(pattGroup);
176            }
[5172]177            pattFile.close();
178        }
179    }
180   
181    // if there are no regexes specified through -e or -f, the first positional argument
182    // must be a regex, not an input file.
183   
184    if (pattVector.size() == 0) {
185        pattVector.push_back(inputFiles[0]);
186        inputFiles.erase(inputFiles.begin());
187    }
188}
189
[5418]190void buildPatternKernel(PabloKernel * const kernel, const std::vector<std::string> & patterns) {
191    PabloBuilder entry(kernel->getEntryBlock());
[5217]192
[5418]193    Var * pat = kernel->getInputStreamVar("pat");
[5217]194
195    PabloAST * basisBits[4];
196
197    basisBits[0] = entry.createExtract(pat, 0, "A");
198    basisBits[1] = entry.createExtract(pat, 1, "C");
199    basisBits[2] = entry.createExtract(pat, 2, "T");
200    basisBits[3] = entry.createExtract(pat, 3, "G");
201
[5418]202    re::Pattern_Compiler pattern_compiler(*kernel);
[5217]203    pattern_compiler.compile(patterns, entry, basisBits, editDistance, optPosition, stepSize);
204
[5418]205    pablo_function_passes(kernel);
[5217]206}
207
[5244]208
[5399]209void editdPipeline(ParabixDriver & pxDriver, const std::vector<std::string> & patterns) {
[5172]210   
[5399]211    IDISA::IDISA_Builder * const iBuilder = pxDriver.getIDISA_Builder();
212    Module * const m = iBuilder->getModule();
[5292]213    Type * const sizeTy = iBuilder->getSizeTy();
[5257]214    Type * const voidTy = iBuilder->getVoidTy();
215    Type * const inputType = PointerType::get(ArrayType::get(ArrayType::get(iBuilder->getBitBlockType(), 8), 1), 0);
216   
[5292]217    Function * const main = cast<Function>(m->getOrInsertFunction("Main", voidTy, inputType, sizeTy, nullptr));
[5257]218    main->setCallingConv(CallingConv::C);
[5399]219    auto args = main->arg_begin();
[5257]220    Value * const inputStream = &*(args++);
221    inputStream->setName("input");
222    Value * const fileSize = &*(args++);
223    fileSize->setName("fileSize");
[5399]224    iBuilder->SetInsertPoint(BasicBlock::Create(m->getContext(), "entry", main,0));
225
226
[5418]227    auto ChStream = pxDriver.addBuffer(make_unique<SourceFileBuffer>(iBuilder, iBuilder->getStreamSetTy(4)));
[5172]228
[5418]229    auto mmapK = pxDriver.addKernelInstance(make_unique<kernel::FileSourceKernel>(iBuilder, inputType));
230    mmapK->setInitialArguments({inputStream, fileSize});
[5399]231
[5418]232    pxDriver.makeKernelCall(mmapK, {}, {ChStream});
[5217]233
[5418]234    auto MatchResults = pxDriver.addBuffer(make_unique<SingleBlockBuffer>(iBuilder, iBuilder->getStreamSetTy(editDistance + 1)));
[5399]235
[5418]236    auto editdk = pxDriver.addKernelInstance(make_unique<PabloKernel>(
237        iBuilder, "editd", std::vector<Binding>{{iBuilder->getStreamSetTy(4), "pat"}}, std::vector<Binding>{{iBuilder->getStreamSetTy(editDistance + 1), "E"}}
238        ));
[5217]239
[5418]240    buildPatternKernel(reinterpret_cast<PabloKernel *>(editdk), patterns);
241    pxDriver.makeKernelCall(editdk, {ChStream}, {MatchResults});
242
243    auto editdScanK = pxDriver.addKernelInstance(make_unique<editdScanKernel>(iBuilder, editDistance));
244    pxDriver.makeKernelCall(editdScanK, {MatchResults}, {});
[5399]245       
246    pxDriver.generatePipelineIR();
[5172]247
[5399]248    iBuilder->CreateRetVoid();
[5172]249
[5399]250    pxDriver.linkAndFinalize();
[5172]251}
252
[5418]253void buildPreprocessKernel(PabloKernel * const kernel) {
254    cc::CC_Compiler ccc(kernel, kernel->getInputStreamVar("basis"));
[5310]255
[5217]256    PabloBuilder & pb = ccc.getBuilder();
257
258    PabloAST * A = ccc.compileCC(re::makeCC(re::makeCC(0x41), re::makeCC(0x61)), pb);
259    PabloAST * C = ccc.compileCC(re::makeCC(re::makeCC(0x43), re::makeCC(0x63)), pb);
260    PabloAST * T = ccc.compileCC(re::makeCC(re::makeCC(0x54), re::makeCC(0x74)), pb);
261    PabloAST * G = ccc.compileCC(re::makeCC(re::makeCC(0x47), re::makeCC(0x67)), pb);
262
[5418]263    Var * const pat = kernel->getOutputStreamVar("pat");
[5217]264
265    pb.createAssign(pb.createExtract(pat, 0), A);
266    pb.createAssign(pb.createExtract(pat, 1), C);
267    pb.createAssign(pb.createExtract(pat, 2), T);
268    pb.createAssign(pb.createExtract(pat, 3), G);
269
[5418]270    pablo_function_passes(kernel);
[5217]271}
272
[5398]273void preprocessPipeline(ParabixDriver & pxDriver) {
274
275    IDISA::IDISA_Builder * iBuilder = pxDriver.getIDISA_Builder();
276    Module * m = iBuilder->getModule();
[5172]277    Type * mBitBlockType = iBuilder->getBitBlockType();
278   
[5418]279
[5254]280    Type * const voidTy = iBuilder->getVoidTy();
[5418]281    Type * const int32Ty = iBuilder->getInt32Ty();
[5254]282    Type * const outputType = PointerType::get(ArrayType::get(mBitBlockType, 4), 0);
283   
[5418]284    Function * const main = cast<Function>(m->getOrInsertFunction("Main", voidTy, int32Ty, outputType, nullptr));
[5254]285    main->setCallingConv(CallingConv::C);
286    Function::arg_iterator args = main->arg_begin();
287   
[5418]288    Value * const fileDescriptor = &*(args++);
289    fileDescriptor->setName("fileDescriptor");
[5254]290    Value * const outputStream = &*(args++);
291    outputStream->setName("output");
[5418]292
[5398]293    iBuilder->SetInsertPoint(BasicBlock::Create(m->getContext(), "entry", main));
294
[5418]295    auto ByteStream = pxDriver.addBuffer(make_unique<SourceFileBuffer>(iBuilder, iBuilder->getStreamSetTy(1, 8)));
[5172]296
[5418]297    auto mmapK = pxDriver.addKernelInstance(make_unique<kernel::MMapSourceKernel>(iBuilder, 1));
298    mmapK->setInitialArguments({fileDescriptor});
299    pxDriver.makeKernelCall(mmapK, {}, {ByteStream});
[5172]300
[5418]301    auto BasisBits = pxDriver.addBuffer(make_unique<SingleBlockBuffer>(iBuilder, iBuilder->getStreamSetTy(8)));
302    auto s2pk = pxDriver.addKernelInstance(make_unique<S2PKernel>(iBuilder));
303    pxDriver.makeKernelCall(s2pk, {ByteStream}, {BasisBits});
[5217]304
[5418]305    auto CCResults = pxDriver.addExternalBuffer(make_unique<ExternalFileBuffer>(iBuilder, iBuilder->getStreamSetTy(4)), outputStream);
[5172]306
[5398]307
[5418]308
309    auto ccck = pxDriver.addKernelInstance(make_unique<PabloKernel>(
310        iBuilder, "ccc", std::vector<Binding>{{iBuilder->getStreamSetTy(8), "basis"}}, std::vector<Binding>{{iBuilder->getStreamSetTy(4), "pat"}}
311        ));
312    buildPreprocessKernel(reinterpret_cast<PabloKernel *>(ccck));
313    pxDriver.makeKernelCall(ccck, {BasisBits}, {CCResults});
314             
[5398]315    pxDriver.generatePipelineIR();
316
[5172]317    iBuilder->CreateRetVoid();
[5398]318
319    pxDriver.linkAndFinalize();
[5172]320}
321
322
[5418]323typedef void (*preprocessFunctionType)(const int fd, char * output_data);
[5172]324
[5398]325preprocessFunctionType preprocessCodeGen() {                           
[5176]326    LLVMContext TheContext;
327    Module * M = new Module("preprocess", TheContext);
[5172]328    IDISA::IDISA_Builder * idb = IDISA::GetIDISA_Builder(M);
[5398]329    ParabixDriver pxDriver(idb);
330    preprocessPipeline(pxDriver);
331    auto f = reinterpret_cast<preprocessFunctionType>(pxDriver.getPointerToMain());
[5172]332    delete idb;
[5398]333    return f;
[5172]334}
335
336typedef void (*editdFunctionType)(char * byte_data, size_t filesize);
337
[5399]338editdFunctionType editdCodeGen(const std::vector<std::string> & patterns) {                           
[5177]339    LLVMContext TheContext;
[5176]340    Module * M = new Module("editd", TheContext);
[5399]341    IDISA::IDISA_Builder * const idb = IDISA::GetIDISA_Builder(M);
342    ParabixDriver pxDriver(idb);
343    editdPipeline(pxDriver, patterns);
344    auto f = reinterpret_cast<editdFunctionType>(pxDriver.getPointerToMain());
[5172]345    delete idb;
[5399]346    return f;
[5172]347}
348
[5418]349static char * chStream;
350static size_t size;
[5212]351
[5418]352size_t file_size(const int fd) {
353    struct stat st;
354    if (LLVM_UNLIKELY(fstat(fd, &st) != 0)) {
355        st.st_size = 0;
356    }
357    return st.st_size;
358}
359
360
[5212]361char * preprocess(preprocessFunctionType fn_ptr) {
[5172]362    std::string fileName = inputFiles[0];
[5418]363    const int fd = open(inputFiles[0].c_str(), O_RDONLY);
364    if (LLVM_UNLIKELY(fd == -1)) {
[5172]365        std::cerr << "Error: cannot open " << fileName << " for processing. Skipped.\n";
[5418]366        exit(-1);
[5172]367    }
[5418]368    size = file_size(fd);
369    int ret = posix_memalign((void**)&chStream, 32, size);
[5212]370    if (ret) {
371        std::cerr << "Cannot allocate memory for output.\n";
[5418]372        exit(-2);
[5212]373    }
[5418]374    fn_ptr(fd, chStream);
375    close(fd);
[5212]376    return chStream;   
[5172]377}
378
[5418]379void editd(editdFunctionType fn_ptr, char * inputStream, size_t size) {
[5172]380 
381    if (size == 0) {
[5212]382        inputStream = nullptr;
[5172]383    }
384
[5212]385    fn_ptr(inputStream, size);
[5172]386   
387}
388
[5244]389std::mutex count_mutex;
390size_t groupCount;
[5418]391void * DoEditd(void *)
[5244]392{
393    size_t groupIdx;
394    count_mutex.lock();
395    groupIdx = groupCount;
396    groupCount++;
397    count_mutex.unlock();
398
399    while (groupIdx < pattGroups.size()){
400        editdFunctionType editd_ptr = editdCodeGen(pattGroups[groupIdx]);
401        editd(editd_ptr, chStream, size);
402
403        count_mutex.lock();
404        groupIdx = groupCount;
405        groupCount++;
406        count_mutex.unlock();
407    }
408
409    pthread_exit(NULL);
410}
411
[5212]412#ifdef CUDA_ENABLED
413
414#define GROUPTHREADS 64
415#define GROUPBLOCKS 64
416
[5213]417void editdGPUCodeGen(unsigned patternLen){ 
[5212]418    LLVMContext TheContext;
419    Module * M = new Module("editd-gpu", TheContext);
420    IDISA::IDISA_Builder * iBuilder = IDISA::GetIDISA_GPU_Builder(M);
421    M->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64");
422    M->setTargetTriple("nvptx64-nvidia-cuda");
423    unsigned addrSpace = 1;
424
425    Type * const mBitBlockType = iBuilder->getBitBlockType();
426    Type * const inputSizeTy = PointerType::get(iBuilder->getSizeTy(), 1);
427    Type * const int32ty = iBuilder->getInt32Ty();
428    Type * const voidTy = Type::getVoidTy(M->getContext());
429    Type * const inputTy = PointerType::get(ArrayType::get(mBitBlockType, 4), 1);
430    Type * const patternPtrTy = PointerType::get(iBuilder->getInt8Ty(), 1);
431    Type * const outputTy = PointerType::get(ArrayType::get(mBitBlockType, editDistance+1), 1);
432    Type * const stridesTy = PointerType::get(int32ty, 1);
433
[5318]434    ExternalFileBuffer CCStream(iBuilder, iBuilder->getStreamSetTy(4), addrSpace);
[5217]435    ExternalFileBuffer ResultStream(iBuilder, iBuilder->getStreamSetTy( editDistance+1, 1), addrSpace);
[5212]436
[5318]437    MMapSourceKernel mmapK(iBuilder);
438    mmapK.generateKernel({}, {&CCStream});
439
[5212]440    kernel::editdGPUKernel editdk(iBuilder, editDistance, patternLen); 
441    editdk.generateKernel({&CCStream}, {&ResultStream});
442
443    Function * const main = cast<Function>(M->getOrInsertFunction("GPU_Main", voidTy, inputTy, inputSizeTy, patternPtrTy, outputTy, stridesTy, nullptr));
444    main->setCallingConv(CallingConv::C);
445    Function::arg_iterator args = main->arg_begin();
446   
447    Value * const inputStream = &*(args++);
448    inputStream->setName("input");
449    Value * const inputSizePtr = &*(args++);
450    inputSizePtr->setName("inputSizePtr");
451    Value * const pattStream = &*(args++);
452    pattStream->setName("pattStream");
453    Value * const resultStream = &*(args++);
454    resultStream->setName("resultStream");
455    Value * const stridesPtr = &*(args++);
456    stridesPtr->setName("stridesPtr");
457   
458    iBuilder->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", main,0));
459
460    Function * tidFunc = M->getFunction("llvm.nvvm.read.ptx.sreg.tid.x");
461    Value * tid = iBuilder->CreateCall(tidFunc);
462    Value * inputThreadPtr = iBuilder->CreateGEP(inputStream, tid);
463
464    Function * bidFunc = cast<Function>(M->getOrInsertFunction("llvm.nvvm.read.ptx.sreg.ctaid.x", int32ty, nullptr));
465    Value * bid = iBuilder->CreateCall(bidFunc);
466    Value * strides = iBuilder->CreateLoad(stridesPtr);
467    Value * outputBlocks = iBuilder->CreateMul(strides, ConstantInt::get(int32ty, GROUPTHREADS));
468    Value * resultStreamPtr = iBuilder->CreateGEP(resultStream, iBuilder->CreateAdd(iBuilder->CreateMul(bid, outputBlocks), tid));
469
470    Value * inputSize = iBuilder->CreateLoad(inputSizePtr);
[5377]471    CCStream.setStreamSetBuffer(inputThreadPtr);
472    ResultStream.setStreamSetBuffer(resultStreamPtr);
[5318]473    mmapK.setInitialArguments({inputSize});
[5212]474
475    const unsigned numOfCarries = patternLen * (editDistance + 1) * 4;
476    Type * strideCarryTy = ArrayType::get(mBitBlockType, numOfCarries);
477    Value * strideCarry = iBuilder->CreateAlloca(strideCarryTy);
478    iBuilder->CreateStore(Constant::getNullValue(strideCarryTy), strideCarry);
479
[5220]480    editdk.setInitialArguments({pattStream, strideCarry});
[5212]481   
[5318]482    generatePipelineLoop(iBuilder, {&mmapK, &editdk});
[5212]483       
484    iBuilder->CreateRetVoid();
485   
486    MDNode * Node = MDNode::get(M->getContext(),
487                                {llvm::ValueAsMetadata::get(main),
488                                 MDString::get(M->getContext(), "kernel"), 
489                                 ConstantAsMetadata::get(ConstantInt::get(iBuilder->getInt32Ty(), 1))});
490    NamedMDNode *NMD = M->getOrInsertNamedMetadata("nvvm.annotations");
491    NMD->addOperand(Node);
492
493    Compile2PTX(M, IRFilename, PTXFilename);
494
495}
496
[5215]497void mergeGPUCodeGen(){
498        LLVMContext TheContext;
499    Module * M = new Module("editd-gpu", TheContext);
500    IDISA::IDISA_Builder * iBuilder = IDISA::GetIDISA_GPU_Builder(M);
501    M->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64");
502    M->setTargetTriple("nvptx64-nvidia-cuda");
503
504    Type * const mBitBlockType = iBuilder->getBitBlockType();
505    Type * const int32ty = iBuilder->getInt32Ty();
506    Type * const voidTy = Type::getVoidTy(M->getContext());
507    Type * const resultTy = PointerType::get(ArrayType::get(mBitBlockType, editDistance+1), 1);
508    Type * const stridesTy = PointerType::get(int32ty, 1);
509
510    Function * const main = cast<Function>(M->getOrInsertFunction("mergeResult", voidTy, resultTy, stridesTy, nullptr));
511    main->setCallingConv(CallingConv::C);
512    Function::arg_iterator args = main->arg_begin();
513   
514    Value * const resultStream = &*(args++);
515    resultStream->setName("resultStream");
516    Value * const stridesPtr = &*(args++);
517    stridesPtr->setName("stridesPtr");
518
519    BasicBlock * entryBlock = BasicBlock::Create(iBuilder->getContext(), "entryBlock", main, 0);
520    BasicBlock * strideLoopCond = BasicBlock::Create(iBuilder->getContext(), "strideLoopCond", main, 0);
521    BasicBlock * strideLoopBody = BasicBlock::Create(iBuilder->getContext(), "strideLoopBody", main, 0);
522    BasicBlock * stridesDone = BasicBlock::Create(iBuilder->getContext(), "stridesDone", main, 0);
523   
524    iBuilder->SetInsertPoint(entryBlock);
525
526    Function * tidFunc = M->getFunction("llvm.nvvm.read.ptx.sreg.tid.x");
527    Value * tid = iBuilder->CreateCall(tidFunc);
528
529    Function * bidFunc = cast<Function>(M->getOrInsertFunction("llvm.nvvm.read.ptx.sreg.ctaid.x", int32ty, nullptr));
530    Value * bid = iBuilder->CreateCall(bidFunc);
531    Value * strides = iBuilder->CreateLoad(stridesPtr);
532    Value * strideBlocks = ConstantInt::get(int32ty, iBuilder->getStride() / iBuilder->getBitBlockWidth());
533    Value * outputBlocks = iBuilder->CreateMul(strides, strideBlocks);
534    Value * resultStreamPtr = iBuilder->CreateGEP(resultStream, tid);
535
536    iBuilder->CreateBr(strideLoopCond);
537    iBuilder->SetInsertPoint(strideLoopCond);
538    PHINode * strideNo = iBuilder->CreatePHI(int32ty, 2, "strideNo");
539    strideNo->addIncoming(ConstantInt::get(int32ty, 0), entryBlock);
540    Value * notDone = iBuilder->CreateICmpULT(strideNo, strides);
541    iBuilder->CreateCondBr(notDone, strideLoopBody, stridesDone);
542 
543    iBuilder->SetInsertPoint(strideLoopBody);
544    Value * myResultStreamPtr = iBuilder->CreateGEP(resultStreamPtr, {iBuilder->CreateMul(strideBlocks, strideNo)});
545    Value * myResultStream = iBuilder->CreateLoad(iBuilder->CreateGEP(myResultStreamPtr, {iBuilder->getInt32(0), bid}));
546    for (unsigned i=1; i<GROUPBLOCKS; i++){
547        Value * nextStreamPtr = iBuilder->CreateGEP(myResultStreamPtr, {iBuilder->CreateMul(outputBlocks, iBuilder->getInt32(i)), bid});
548        myResultStream = iBuilder->CreateOr(myResultStream, iBuilder->CreateLoad(nextStreamPtr));
549    }   
550    iBuilder->CreateStore(myResultStream, iBuilder->CreateGEP(myResultStreamPtr, {iBuilder->getInt32(0), bid}));
551    strideNo->addIncoming(iBuilder->CreateAdd(strideNo, ConstantInt::get(int32ty, 1)), strideLoopBody);
552    iBuilder->CreateBr(strideLoopCond);
553   
554    iBuilder->SetInsertPoint(stridesDone);
555    iBuilder->CreateRetVoid();
556   
557    MDNode * Node = MDNode::get(M->getContext(),
558                                {llvm::ValueAsMetadata::get(main),
559                                 MDString::get(M->getContext(), "kernel"), 
560                                 ConstantAsMetadata::get(ConstantInt::get(iBuilder->getInt32Ty(), 1))});
561    NamedMDNode *NMD = M->getOrInsertNamedMetadata("nvvm.annotations");
562    NMD->addOperand(Node);
563
564    Compile2PTX(M, "merge.ll", "merge.ptx");
565
566}
567
[5212]568editdFunctionType editdScanCPUCodeGen() {
569                           
570    LLVMContext TheContext;
571    Module * M = new Module("editd", TheContext);
572    IDISA::IDISA_Builder * iBuilder = IDISA::GetIDISA_Builder(M);
573    ExecutionEngine * editdEngine = nullptr;
574
575    Type * mBitBlockType = iBuilder->getBitBlockType();
576    Type * const size_ty = iBuilder->getSizeTy();
577    Type * const voidTy = Type::getVoidTy(M->getContext());
[5213]578    Type * const inputType = PointerType::get(ArrayType::get(mBitBlockType, editDistance+1), 0);
[5212]579
[5217]580    ExternalFileBuffer MatchResults(iBuilder, iBuilder->getStreamSetTy( editDistance+1, 1));
[5318]581
582    MMapSourceKernel mmapK(iBuilder);
583    mmapK.generateKernel({}, {&MatchResults});
584
[5212]585    kernel::editdScanKernel editdScanK(iBuilder, editDistance);
586    editdScanK.generateKernel({&MatchResults}, {});               
587   
588    Function * const main = cast<Function>(M->getOrInsertFunction("CPU_Main", voidTy, inputType, size_ty, nullptr));
589    main->setCallingConv(CallingConv::C);
590    Function::arg_iterator args = main->arg_begin();
591   
592    Value * const inputStream = &*(args++);
593    inputStream->setName("input");
594    Value * const fileSize = &*(args++);
595    fileSize->setName("fileSize");
596   
597    iBuilder->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", main,0));
598
[5377]599    MatchResults.setStreamSetBuffer(inputStream);
[5318]600    mmapK.setInitialArguments({fileSize});
[5212]601   
[5318]602    generatePipelineLoop(iBuilder, {&mmapK, &editdScanK});
[5212]603       
604    iBuilder->CreateRetVoid();
605
606    editdEngine = JIT_to_ExecutionEngine(M);
607   
608    editdEngine->finalizeObject();
609
610    return reinterpret_cast<editdFunctionType>(editdEngine->getPointerToFunction(main));
611}
612
613#endif
614
[5172]615int main(int argc, char *argv[]) {
616
617    cl::ParseCommandLineOptions(argc, argv);
618
[5173]619    int pattern_segs = 0;
620    int total_len = 0;
[5172]621
[5173]622    get_editd_pattern(pattern_segs, total_len);
[5212]623
624#ifdef CUDA_ENABLED
625    codegen::BlockSize = 64;
626#endif
627
[5172]628    preprocessFunctionType preprocess_ptr = preprocessCodeGen();
[5212]629    preprocess(preprocess_ptr);
[5172]630
[5212]631#ifdef CUDA_ENABLED 
632    setNVPTXOption();   
[5213]633    if(codegen::NVPTX){
[5212]634
635        std::ifstream t(PatternFilename);
636        if (!t.is_open()) {
637            std::cerr << "Error: cannot open " << PatternFilename << " for processing. Skipped.\n";
638            exit(-1);
639        } 
[5213]640        std::string patterns((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
[5212]641
[5213]642        editdGPUCodeGen(patterns.length()/GROUPTHREADS - 1);
[5212]643
[5215]644        mergeGPUCodeGen();
645
[5213]646        ulong * rslt = RunPTX(PTXFilename, chStream, size, patterns.c_str(), patterns.length(), editDistance);
647
[5212]648        editdFunctionType editd_ptr = editdScanCPUCodeGen();
649
650        editd(editd_ptr, (char*)rslt, size);
[5215]651       
[5173]652        run_second_filter(pattern_segs, total_len, 0.15);
653
[5212]654        return 0;
655    }
656#endif
657   
658    if(pattVector.size() == 1){
659        editdFunctionType editd_ptr = editdCodeGen(pattVector);
660        editd(editd_ptr, chStream, size);
661    }
662    else{
[5244]663        if (Threads == 1) {
664            for(unsigned i=0; i<pattGroups.size(); i++){
665                editdFunctionType editd_ptr = editdCodeGen(pattGroups[i]);
666                editd(editd_ptr, chStream, size);
667            }
[5212]668        }
[5244]669        else{
670            const unsigned numOfThreads = Threads;
671            pthread_t threads[numOfThreads];
672            groupCount = 0;
673
674            for(unsigned long i = 0; i < numOfThreads; ++i){
675                const int rc = pthread_create(&threads[i], NULL, DoEditd, (void *)i);
676                if (rc) {
677                    llvm::report_fatal_error("Failed to create thread: code " + std::to_string(rc));
678                }
679            }
680
681            for(unsigned i = 0; i < numOfThreads; ++i) {
682                void * status = nullptr;
683                const int rc = pthread_join(threads[i], &status);
684                if (rc) {
685                    llvm::report_fatal_error("Failed to join thread: code " + std::to_string(rc));
686                }
687            }
688
689        }
[5212]690        run_second_filter(pattern_segs, total_len, 0.15);
691    }
[5172]692
693    return 0;
694}
Note: See TracBrowser for help on using the repository browser.