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

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

More fixes for editd.

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