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

Last change on this file since 5583 was 5583, checked in by lindanl, 4 months ago

Another cache naming bug fixed for editd.

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