source: docs/Working/icGrep/architecture.tex @ 4499

Last change on this file since 4499 was 4499, checked in by nmedfort, 4 years ago

Cleaned up architecture discussion a bit more

File size: 7.1 KB
2\paragraph{Regular Expression Preprocessing.}
6As shown in Figure \ref{fig:compiler},
7compilation in \icGrep{} comprises three logical layers: \RegularExpression{},
8\Pablo{} and the LLVM layer, each with their own intermediate representation
9(IR), transformation and compilation modules.
11As we traverse the layers, the IR becomes more complex as it begins to mirror the final machine code.
13The layering enables further optimization based on information available at each stage.
15The initial \REParser{} validates and transforms the input \RegularExpression{} into an abstract syntax tree (AST).
17%The AST is a minimalistic representation that, unlike traditional \RegularExpression{}, is not converted into a NFA or DFA for further processing.
19%Instead, \icGrep{} passes the AST into the transformation module, which includes a set of \RegularExpression{} specific optimization passes.
21Successive \RegularExpression{} Transformations exploit knowledge domain
22knowledge to optimize the regular expressions.
24An initial \emph{Nullable} pass, determines whether the \RegularExpression{}
25contains prefixes or suffixes that may be removed or
26modified whilst matching the same lines of text as the original expression.
28For example, ``\verb|a*bc+|'' is equivalent to ``\verb|bc|'' because the Kleene Star (Plus) operator matches zero (one) or more instances of a
29specific character.
31The aforementioned \texttt{toUTF8} transformation also applies during this phase to generate code unit classes.
32%The \emph{toUTF8} pass converts the Unicode character classes in the input \RegularExpression{} into equivalent expression(s) that represent sequences
33%of 8-bit code units necessary to identify occurrences of the class.
35%Since some characters have multiple logically equivalent representations, such as \textcolor{red}{\textbf{????}}, this may produce nested sequences or alternations.
37%This is described in more detail in \S\ref{sec:Unicode:toUTF8}.
39A final \emph{Simplification} pass flattens nested structures into their simplest legal form.
41For example, ``\verb`a(b((c|d)|e))`'' becomes ``\verb`ab(c|d|e)`'' and ``\verb`([0-9]{3,5}){3,5}`'' becomes ``\verb`[0-9]{9,25}`''.
47The next layer transforms this AST into the instructions in the \Pablo{} IR.
49%has two compilers: the \CodeUnitCompiler{} and \RegularExpressionCompiler{}, both of which produce \Pablo{} IR.
51Recall that the \Pablo{} layer assumes a transposed view of the input data.
53The \emph{\RegularExpressionCompiler{}} first transforms all input code unit classes,
54analogous to non-Unicode character classes,
55into a series of equations over these transposed bitstreams.
56It next transforms the AST into \Pablo{} instructions that use the
57results of these equations.
58For instance, it converts alternations into a sequence of calculations that
59are merged with \verb|OR|s.
60The results of these passes are combined and transformed through typical
61optimization passes including dead code elimination
62(DCE), common subexpression elimination (CSE) and constant folding.
63These optimizations exploit redundancies that are harder to recognize in
64the \RegularExpression{} AST itself.
66%The \emph{\CodeUnitCompiler{}} transforms the input code unit classes,
67%either extracted from the \RegularExpression{} or produced by the \emph{toUTF8} transformation,
68%into a series of bit stream equations.
70%The \emph{\RegularExpressionCompiler{}}
71%assumes that these have been calculated and
72%transforms the \RegularExpression{} AST into
73%a sequence of instructions.
74%\Pablo{} instructions that use the results of these equations.
76%For instance, it converts alternations into a sequence of calculations that are merged with \verb|OR|s.
78%The results of these passes are combined and transformed through a series of typical optimization passes, including dead code elimination
79%(DCE), common subexpression elimination (CSE), and constant folding.
81%These optimizations exploit redundancies that are harder to recognize in the \RegularExpression{} AST itself.
82%These are necessary at this stage because the \RegularExpression{} AST may include common subsequences that are costly to recognize in
83%that form.
85%Similarly, to keep the \CodeUnitCompiler{} a linear time function, it may introduce redundant IR instructions as it applies traditional Boolean
86%algebra transformations, such as de Morgan's law, to the computed streams.
88%An intended side-effect of these passes is that they eliminate the need to analyze the data-dependencies inherent in the carry-bit logic,
89%which is necessary for some \Pablo{} instructions but problematic for optimizers to reason about non-conservatively.
92The \PabloCompiler{} then directly converts the \Pablo{} IR into LLVM IR.
94%This is a relatively straightforward conversion:
96%the only complexities it introduces is the generation of Phi nodes, linking of statically-compiled functions, and assignment of carry variables.
98The LLVM Compiler framework provides flexible APIs for compilation and linking.
99Using these, \icGrep{} dynamically generates a match function for identifying
100occurrences of the \RegularExpression{}.
102\paragraph{Dynamic Grep Engine.}
104Figure~\ref{fig:execution} shows the structure of the \icGrep{} matching engine.
105The input data is transposed into 8 parallel bit streams through the Transposition module.
106Using the 8 basis bits streams, the Required Streams Generator computes the
107line break streams, UTF-8 validation streams and the Initial and NonFinal streams
108needed to support ScanThru and MatchStar with UTF-8 data.
109The Dynamic Matcher, dynamically compiled via LLVM, retrieves the 8 basis bits and the required streams from their memory addresses and starts the matching process.
110During the matching process, any references to named Unicode properties generate calls to the appropriate routine in the Named Property Library.
111The Dynamic Matcher returns one bitstream that marks all the positions that fully match the compiled regular expression.
112Finally, a Match Scanner scans through the returned bitstream to select the matching lines and generate the normal grep output.
114We can also apply a pipeline parallelism strategy to further speed up the process of \icGrep{}.
115Transposition and the Required Streams Generator can be performed in a separate thread which can start even before the dynamic compilation starts.
116The output of Transposition and the Required Streams Generator, that is the 8 basis bits streams and the required streams,
117are stored in a shared memory buffer for subsequent processing by the Dynamic Matcher once compilation is complete.
118A single thread performs both compilation and matching using the computed basis and required streams.
119To avoid L2 cache contention, we allocate only a limited amount of space for the shared data in a circular buffer.
120The performance is dependent on the slowest thread.   
121In the case that the cost of transposition and required stream generation is more than the matching process,
122we can further divide up the work and assign two threads for Transposition and the Required Streams Generator.
Note: See TracBrowser for help on using the repository browser.