source: icGREP/icgrep-devel/icgrep/icgrep.cpp @ 4080

Last change on this file since 4080 was 4080, checked in by cameron, 5 years ago

Add munmap call

File size: 15.3 KB
Line 
1/*
2 *  Copyright (c) 2014 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 "icgrep.h"
8
9#include "utf_encoding.h"
10#include "re_compiler.h"
11
12#include <fstream>
13#include <sstream>
14#include <iostream>
15#include <string>
16#include <stdint.h>
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <errno.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24
25#include <simd-lib/bitblock.hpp>
26#include <simd-lib/carryQ.hpp>
27#include <simd-lib/pabloSupport.hpp>
28#include <simd-lib/s2p.hpp>
29#include <simd-lib/buffer.hpp>
30#include <simd-lib/bitblock_iterator.hpp>
31
32// mmap system
33#include <sys/mman.h>
34#include <fcntl.h>
35
36
37#define SEGMENT_BLOCKS 15
38#define SEGMENT_SIZE (BLOCK_SIZE * SEGMENT_BLOCKS)
39
40#define BUFFER_SEGMENTS 15
41#define BUFFER_SIZE (BUFFER_SEGMENTS * SEGMENT_SIZE)
42
43#define BitBlock_declare(name)  BitBlock name
44
45#define ubitblock_declare(name, n) \
46  ubitblock name[n];\
47  do {int i;\
48      for (i = 0; i < n; i++) name[i]._128 = simd<1>::constant<0>();\
49     }\
50  while (0)
51
52BitBlock EOF_mask = simd<1>::constant<1>();
53
54struct Output {
55    BitBlock matches;
56    BitBlock LF;
57};
58
59#include <simd-lib/transpose.hpp>
60
61using namespace std;
62
63typedef void (*process_block_fcn)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output);
64
65
66#define USE_MMAP
67#ifndef USE_MMAP
68void do_process(FILE *infile, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block);
69#endif
70#ifdef USE_MMAP
71void do_process(char * infile_buffer, size_t infile_size, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block);
72#endif
73
74BitBlock get_category(Basis_bits &basis_bits, const char* category);
75
76int main(int argc, char *argv[])
77{
78    char * inregex, * fileregex, * infilename, * outfilename;
79    FILE *infile, *outfile, *regexfile;
80
81#ifdef USE_MMAP
82    int fdSrc;
83    struct stat infile_sb;
84    char * infile_buffer;
85#endif
86   
87    int opt_code;
88    int count_only_option = 0;
89    int print_version_option = 0;
90    int regex_from_file_option = 0;
91    int ascii_only_option = 0;
92
93    int compile_time_option = 0;
94
95    unsigned long long cycles = 0;
96    double timer = 0;
97
98    long lSize = 0;
99
100    size_t result;
101
102    while ((opt_code = getopt(argc, argv, "cvfta")) != -1)
103    {
104        switch (opt_code)
105        {
106        case 'c':
107            count_only_option = 1;
108            break;
109        case 'v':
110            print_version_option = 1;
111            break;
112        case 'f':
113            regex_from_file_option = 1;
114            break;
115        case 't':
116            compile_time_option = 1;
117            break;
118        case 'a':
119            ascii_only_option = 1;
120            break;
121        case '?':
122            break;
123        default:
124            printf ("Invalid option: %c\n", opt_code);
125            printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
126                    exit(-1);
127        }
128    }
129
130    if (optind >= argc)
131    {
132        printf ("Too few arguments\n");
133        printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
134        exit(-1);
135    }
136
137    inregex = argv[optind++];
138    if (inregex == 0)
139    {
140        fprintf(stderr, "Error: cannot read the regular expression.\n");
141        exit(-1);
142    }
143
144    if (regex_from_file_option)
145    {
146        regexfile = fopen(inregex, "rb");
147        if (!regexfile){
148            fprintf(stderr, "Error: cannot open %s for processing.\n", inregex);
149            exit(-1);
150        }
151
152        fseek (regexfile , 0 , SEEK_END);
153        lSize = ftell (regexfile);
154        rewind (regexfile);
155
156        fileregex = (char*) malloc (sizeof(char)*lSize);
157        if (fileregex == NULL) {fputs ("Memory error",stderr); exit (2);}
158
159        result = fread (fileregex, 1, lSize, regexfile);
160        if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
161        fclose(regexfile);
162
163        if (fileregex[lSize - 1] == '\n') fileregex[lSize - 1] = '\0';
164    }
165
166    infilename = argv[optind++];
167#ifndef USE_MMAP
168    infile = fopen(infilename, "rb");
169    if (!infile) {
170        fprintf(stderr, "Error: cannot open %s for processing.\n", infilename);
171        exit(-1);
172    }
173#endif
174#ifdef USE_MMAP
175    fdSrc = open(infilename, O_RDONLY);
176    if (fdSrc == -1) {
177        fprintf(stderr, "Error: cannot open %s for processing.\n", infilename);
178        exit(-1);
179    }
180    if (fstat(fdSrc, &infile_sb) == -1) {
181        fprintf(stderr, "Error: cannot stat %s for processing.\n", infilename);
182        exit(-1);
183    }
184    if (infile_sb.st_size == 0) {
185        if (count_only_option) fprintf(outfile, "Matching Lines%d\n", 0);
186        exit(0);
187    }
188    infile_buffer = (char *) mmap(NULL, infile_sb.st_size, PROT_READ, MAP_PRIVATE, fdSrc, 0);
189    if (infile_buffer == MAP_FAILED) {
190        fprintf(stderr, "Error: mmap of %s failure.\n", infilename);
191        exit(-1);
192    }
193#endif
194
195    if (optind >= argc) outfile = stdout;
196    else
197    {
198        outfilename = argv[optind++];
199        if (optind != argc)
200        {
201            printf ("Too many arguments\n");
202            printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
203            exit(-1);
204        }
205        outfile = fopen(outfilename, "wb");
206        if (!outfile)
207        {
208            fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
209            exit(-1);
210        }
211    }
212
213    if (print_version_option)
214    {
215        fprintf(outfile, "Parabix icgrep implementation: August 2014\n");
216    }
217
218    UTF_Encoding encoding;
219    encoding.setName("UTF-8");
220    encoding.setBits(8);
221    encoding.setMask(0xFF);
222
223    RE_Compiler* re_compiler = new RE_Compiler();
224    if (compile_time_option)
225    {
226        cycles = get_hrcycles();
227        timer = getElapsedTime();
228    }
229    LLVM_Gen_RetVal llvm_codegen = re_compiler->compile(compile_time_option,
230                                                        ascii_only_option,
231                                                        "basis_bits.bit_",
232                                                        "temp",
233                                                        encoding ,
234                                                        (regex_from_file_option ? fileregex : inregex));
235
236    if (compile_time_option)
237    {
238        cycles = get_hrcycles() - cycles;
239        timer = getElapsedTime() - timer;
240        std::cout << "Total compile time - cycles:       " << cycles << std::endl;
241        std::cout << "Total compile time - milliseconds: " << timer << std::endl;
242    }
243
244    if (llvm_codegen.process_block_fptr != 0)
245    {
246        void (*FP)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output) = (void (*)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output))(void*)llvm_codegen.process_block_fptr;
247#ifndef USE_MMAP
248        do_process(infile, outfile, count_only_option, llvm_codegen.carry_q_size, FP);
249#endif
250#ifdef USE_MMAP
251        do_process(infile_buffer, infile_sb.st_size, outfile, count_only_option, llvm_codegen.carry_q_size, FP);
252#endif
253    }
254
255    delete re_compiler;
256#ifndef USE_MMAP
257    fclose(infile);
258#endif
259#ifdef USE_MMAP
260    munmap((void *) infile_buffer, infile_sb.st_size);
261    close(fdSrc);
262#endif
263    fclose(outfile);
264    if (regex_from_file_option) free(fileregex);
265
266    return 0;
267}
268
269#ifndef USE_MMAP
270void do_process(FILE *infile, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block) {
271#endif
272#ifdef USE_MMAP
273void do_process(char * infile_buffer, size_t infile_size, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block) {
274#endif
275
276    struct Basis_bits basis_bits;
277    struct Output output;
278
279    BitBlock carry_q[carry_count];
280    memset (carry_q, 0, sizeof(BitBlock) * carry_count);
281
282    BitBlock match_vector = simd<1>::constant<0>();
283    int match_count=0;
284    int blk = 0;
285    int block_base  = 0;
286    int block_pos   = 0;
287    int buffer_pos  = 0;
288    int chars_avail = 0;
289    int chars_read  = 0;
290
291    int line_start = 0;
292    int line_end = 0;
293    int match_pos = 0;
294    int line_no = 0;
295
296    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> LF_scanner;
297    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> match_scanner;
298       
299   
300#ifndef USE_MMAP
301    ATTRIBUTE_SIMD_ALIGN char src_buffer[SEGMENT_SIZE];
302   
303    chars_read = fread((void *)&src_buffer[0], 1, SEGMENT_SIZE, infile);
304    chars_avail = chars_read;
305    if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
306#endif
307#ifdef USE_MMAP   
308    int segment = 0;
309    int segment_base = 0;
310    chars_avail = infile_size;
311   
312#endif
313//////////////////////////////////////////////////////////////////////////////////////////
314// Full Segments
315//////////////////////////////////////////////////////////////////////////////////////////
316
317   
318   
319    while (chars_avail >= SEGMENT_SIZE) {
320
321#ifdef USE_MMAP
322        segment_base = segment * SEGMENT_SIZE;
323#endif
324        LF_scanner.init();
325        match_scanner.init();
326
327        for (blk = 0; blk < SEGMENT_BLOCKS; blk++) {
328#ifndef USE_MMAP
329            block_base = blk*BLOCK_SIZE;
330            s2p_do_block((BytePack *) &src_buffer[block_base], basis_bits);
331#endif
332#ifdef USE_MMAP
333            block_base = blk*BLOCK_SIZE + segment_base;
334            s2p_do_block((BytePack *) &infile_buffer[block_base], basis_bits);   
335#endif
336            process_block(basis_bits, carry_q, output);
337
338            LF_scanner.load_block(output.LF, blk);
339            match_scanner.load_block(output.matches, blk);
340            if (count_only_option){
341                if (bitblock::any(output.matches))
342                {
343                    if (bitblock::any(simd_and(match_vector, output.matches))){
344                        match_count += bitblock::popcount(match_vector);
345                        match_vector = output.matches;
346                    }
347                    else
348                    {
349                        match_vector = simd_or(match_vector, output.matches);
350                    }
351                }
352            }
353        }
354
355#ifndef USE_MMAP
356        int copy_back_pos = 0;
357
358
359        if (LF_scanner.count() > 0) {
360            copy_back_pos = LF_scanner.get_final_pos() + 1;
361            memset (carry_q, 0, sizeof(BitBlock) * carry_count);
362        }
363        else {
364            copy_back_pos =  SEGMENT_SIZE;
365        }
366
367        int  copy_back_size = SEGMENT_SIZE - copy_back_pos;
368#endif
369#ifdef USE_MMAP
370   
371#endif
372
373        if (!count_only_option) {
374#ifndef USE_MMAP
375            line_start = 0;
376#endif
377
378            while (match_scanner.has_next()) {
379                match_pos = match_scanner.scan_to_next();
380                line_end = LF_scanner.scan_to_next();
381                while (line_end < match_pos) {
382                    line_start = line_end+1;
383                    line_no++;
384                    line_end = LF_scanner.scan_to_next();
385                }
386#ifndef USE_MMAP
387                fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
388#endif
389#ifdef USE_MMAP
390                fwrite(&infile_buffer[segment_base + line_start], 1, line_end - line_start + 1, outfile);
391 
392#endif
393
394                line_start = line_end+1;
395                line_no++;
396            }
397            while (LF_scanner.has_next()) {
398                line_end = LF_scanner.scan_to_next();
399                line_start = line_end+1;
400                line_no++;
401            }
402
403        }
404#ifndef USE_MMAP
405        memmove(&src_buffer[0], &src_buffer[copy_back_pos], copy_back_size);
406
407        //Do another read.
408        chars_read = fread(&src_buffer[copy_back_size], 1, copy_back_pos, infile);
409        chars_avail = chars_read + copy_back_size;
410        if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
411        buffer_pos += chars_avail;
412#endif
413#ifdef USE_MMAP
414        segment++;
415        line_start -= SEGMENT_SIZE;  /* Will be negative offset for use within next segment. */
416        chars_avail -= SEGMENT_SIZE;
417   
418#endif
419    }
420
421
422//////////////////////////////////////////////////////////////////////////////////////////
423// For the Final Partial Segment.
424//////////////////////////////////////////////////////////////////////////////////////////
425
426#ifdef USE_MMAP
427    segment_base = segment * SEGMENT_SIZE;
428#endif
429    int remaining = chars_avail;
430
431    LF_scanner.init();
432    match_scanner.init();
433
434    /* Full Blocks */
435    blk = 0;
436    while (remaining >= BLOCK_SIZE) {
437    //fprintf(outfile, "Remaining = %i\n", remaining);
438#ifndef USE_MMAP
439        block_base = block_pos;
440        s2p_do_block((BytePack *) &src_buffer[block_base], basis_bits);
441#endif
442#ifdef USE_MMAP
443        block_base = block_pos + segment_base;
444        s2p_do_block((BytePack *) &infile_buffer[block_base], basis_bits);   
445#endif
446        process_block(basis_bits, carry_q, output);
447
448        LF_scanner.load_block(output.LF, blk);
449        match_scanner.load_block(output.matches, blk);
450        if (count_only_option)
451        {
452            if (bitblock::any(output.matches))
453            {
454                if (bitblock::any(simd_and(match_vector, output.matches)))
455                {
456                    match_count += bitblock::popcount(match_vector);
457                    match_vector = output.matches;
458                }
459                else
460                {
461                    match_vector = simd_or(match_vector, output.matches);
462                }
463            }
464        }
465
466        block_pos += BLOCK_SIZE;
467        remaining -= BLOCK_SIZE;
468        blk++;
469    }
470    block_base = block_pos;
471    //fprintf(stderr, "Remaining = %i\n", remaining);
472
473    //For the last partial block, or for any carry.
474    EOF_mask = bitblock::srl(simd<1>::constant<1>(), convert(BLOCK_SIZE-remaining));
475#ifndef USE_MMAP
476     block_base = block_pos;
477     s2p_do_final_block((BytePack *) &src_buffer[block_base], basis_bits, EOF_mask);
478#endif
479#ifdef USE_MMAP
480     block_base = block_pos + segment_base;
481     s2p_do_final_block((BytePack *) &infile_buffer[block_base], basis_bits, EOF_mask);   
482#endif
483    process_block(basis_bits, carry_q, output);
484
485    if (count_only_option)
486    {
487        match_count += bitblock::popcount(match_vector);
488        if (bitblock::any(output.matches))
489        {
490            match_count += bitblock::popcount(output.matches);
491        }
492        fprintf(outfile, "Matching Lines:%d\n", match_count);
493    }
494    else
495    {
496        LF_scanner.load_block(output.LF, blk);
497        match_scanner.load_block(output.matches, blk);
498        blk++;
499        for (int i = blk; i < SEGMENT_BLOCKS; i++)
500        {
501            LF_scanner.load_block(simd<1>::constant<0>(), i);
502            match_scanner.load_block(simd<1>::constant<0>(), i);
503        }
504#ifndef USE_MMAP
505        line_start = 0;
506#endif
507        while (match_scanner.has_next())
508        {
509            match_pos = match_scanner.scan_to_next();
510            line_end = LF_scanner.scan_to_next();
511            while(line_end < match_pos)
512            {
513                line_start = line_end + 1;
514                line_no++;
515                line_end = LF_scanner.scan_to_next();
516            }
517#ifndef USE_MMAP
518            fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
519#endif
520#ifdef USE_MMAP
521            fwrite(&infile_buffer[segment_base + line_start], 1, line_end - line_start + 1, outfile);
522 
523#endif
524            line_start = line_end + 1;
525            line_no++;
526        }
527        while(LF_scanner.has_next())
528        {
529            line_end = LF_scanner.scan_to_next();
530            line_start = line_end+1;
531            line_no++;
532        }
533    }
534
535    buffer_pos += chars_avail;
536}
537
538
539
Note: See TracBrowser for help on using the repository browser.