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

Last change on this file since 5597 was 5597, checked in by nmedfort, 23 months ago

Modified stream set buffers to use heap memory.

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