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

Last change on this file since 5579 was 5579, checked in by lindanl, 2 years ago

multiple editd kernels in one pipeline

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