You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: kiselyov.md
+61-1Lines changed: 61 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -232,6 +232,7 @@ the previous example with two variables.
232
232
Now the Kiselyov algorithms really start to shine. `compileEta` produces code is significantly smaller as the baseline. And `compileBulk` output is even smaller.
233
233
234
234
235
+
235
236
### The tak function
236
237
237
238
```haskell
@@ -255,13 +256,72 @@ main = tak 7 4 2
255
256
256
257
In this example with four variables the trend continues. `compileEta` produces code is significantly smaller as the baseline. And `compileBulk` output now is only about 1/3 of the baseline.
257
258
259
+
## Executing Bulk Combinators
260
+
261
+
We have seen that Kisekyov's algorithms produce code that makes use of *Bulk Combinators* like `S4`, `B3` or `C2`. Ben Lynn defines the semantics of these combinators as follows:
Ben also defines the following function that converts a combinator term with *Bulk Combinators* to a combinator term with only standard combinators:
270
+
271
+
```haskell
272
+
breakBulkLinear::Combinator->Int->CL
273
+
breakBulkLinear B n =iterate (comB' :@) (ComB) !! (n -1)
274
+
breakBulkLinear C n =iterate (comC' :@) (ComC) !! (n -1)
275
+
breakBulkLinear S n =iterate (comS' :@) (ComS) !! (n -1)
276
+
277
+
comB'::CL
278
+
comB' =ComB:@ComB
279
+
comC'::CL
280
+
comC' =ComB:@ (ComB:@ComC) :@ComB
281
+
comS'::CL
282
+
comS' =ComB:@ (ComB:@ComS) :@ComB
283
+
```
284
+
285
+
As we have seen in the output of the `compileBulkLinear` this conversion expands the code size. To avoid this expansion of the combinator code I have implemented a solution to directly execute *Bulk Combinators*.
286
+
287
+
At the moment I have only implemented it in the [Haskell-In-Haskell](https://wiki.haskell.org/wikiupload/0/0a/TMR-Issue10.pdf) inspired HHI-Reducer. Implementing it for the Graph Reduction Engine is left as an exercise for the reader ;-).
288
+
289
+
```haskell
290
+
--| apply a CExpr of shape (CFun f) to argument x by evaluating (f x)
291
+
infixl0!
292
+
(!)::CExpr->CExpr->CExpr
293
+
(CFun f) ! x = f x
294
+
295
+
--| "link" a compiled expression into Haskell native functions.
296
+
-- application terms will be transformed into real (!) applications
297
+
-- combinator symbols will be replaced by their actual function definition
298
+
link::CombinatorDefinitions->CExpr->CExpr
299
+
link definitions (CApp fun arg) = link definitions fun ! link definitions arg
300
+
link definitions (CComb comb) =caselookup comb definitions of
comS =CFun (\f ->CFun$\g ->CFun$\x -> f!x!(g!x)) -- S F G X = F X (G X)
313
+
314
+
comS'::CExpr
315
+
comS' =CFun (\p ->CFun$\q ->CFun$\r ->CFun$\s -> p!(q!s)!(r!s)) -- S' P Q R S = P (Q S) (R S)
316
+
```
317
+
258
318
259
319
## performance comparison
260
320
261
321
So far we have seen that for functions with more than two variables the Kiselyov algorithms generate code that is significantly smaller than optimized versions of classic bracket abstraction.
262
322
But what about performance? Is the code generated by the Kiselyov algorithms also faster?
263
323
264
-
To answer this question i have implemented a simple benchmarking suite based on the [micro-benchmarking framework Criterion](http://www.serpentine.com/criterion/).
324
+
To answer this question I have set up a benchmarking suite based on the [micro-benchmarking framework Criterion](http://www.serpentine.com/criterion/).
265
325
266
326
In my suite I am testing the performance of combinations of the following components:
0 commit comments