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

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

Continued refactoring work. PabloKernel? now abstract base type with a 'generatePabloMethod' hook to generate Pablo code.

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