Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

perllVm: A Linux test of how Perl and LLVM would work together.

by flexvault (Parson)
on Sep 06, 2012 at 19:31 UTC ( #992174=perlmeditation: print w/ replies, xml ) Need Help??

Dear Monks,

I have been asked to test the LLVM environment for compiling Perl on Linux, similar to what BrowserUK did for windows. At first, I used the Debian “squeeze” Release 'apt-get' to get the LLVM package version 2.7. It installed fine, but couldn't compile Perl5.16.0.

I contacted Sylvestre Ledru who quickly responded that "Perl seems to build fine during my latest rebuild with clang 3.1." So I set out to build the LLVM environment from source. The steps are below and hopefully I used the <readmore> correctly.

Just a caution, this takes a lot of time to compile and may need as much as 3GB of space. So plan accordingly. Also notice that

../llvm/configure --enable-optimized --disable-assertions
you need to add '--disable-assertions' because LLVM is built in debug mode by default.

mkdir /home/llvm/ # Home directory for LLVM versions cd /home/llvm/ # change directory to LLVM HOME mkdir llvm-3.2.src/ # make directory for version cd llvm-3.2.src/ # change directory for LLVM verson # Creates the 'llvm' directory in /home/llvm/llvm-3.2.src/ # This gives the directory structure for the build process svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm cd llvm/tools # where to install clang # Creates the 'clang' directory in /home/llvm/llvm-3.2.src/llvm/tools/ svn co http://llvm.org/svn/llvm-project/cfe/trunk clang cd ../projects/ # where to install compiler-rt svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt cd .. mkdir build/ cd build/ ## Update: added --enable-jit to next line to always enable ../llvm/configure --enable-optimized --disable-assertions --enable-jit + ## Update: next line was missing 'make' first, then 'make check-all' t +o test make make check-all ### note: using clang: '/home/llvm/llvm-3.1.src/build/Release/bin/clan +g' make update /home/llvm/llvm-3.1.src/build# ./Release/bin/clang -v clang version 3.2 (trunk 163314) Target: i386-pc-linux-gnu Thread model: posix /home/llvm/llvm-3.1.src/build# make install make -C runtime install-bytecode make install

We now have a LLVM build including clang 3.1 compiler! We can now compile Perl with 'clang'

cd /home/pyr/PRODUCTS/perl/perllvm email7:/home/pyr/PRODUCTS/perl/perllvm# clang -v clang version 3.2 (trunk 163323) Target: i386-pc-linux-gnu Thread model: posix tar -xf./perl-5.16.0.tar cd perl-5.16.0 ./Configure -des -Dprefix=/usr/opt/perllVm -Dusethreads -Dcc=clang -D +ccflags='-O2' make make tests make install

We now have a Perl 5.16.0 built with 'clang' 3.1. 100% of the Perl tests ran correctly, which says good things about the 5.16.0 distribution. Some tests follow. I tested the Debian default 5.10.0, a 5.16.0 that I compiled with 'gcc' and finally the 5.16.0 built with 'clang'.

email7:/home/pyr/PRODUCTS/perl/perllvm# cat BrowserUK_991333.pl #!perl -sw use strict; use 5.010; use Time::HiRes qw[ time ]; no warnings 'recursion'; sub Ack { my( $M, $N ) = @_; return $N + 1 if $M == 0; return Ack( $M - 1, 1 ) if $N == 0; return Ack( $M - 1, Ack( $M, $N - 1 ) ); } my $start = time; say Ack( @ARGV ); say 'Took: ', time() - $start; email7:/home/pyr/PRODUCTS/perl/perllvm# perl5.10.0 -sw BrowserUK_99133 +3.pl 3 9 4093 Took: 15.1458311080933 email7:/home/pyr/PRODUCTS/perl/perllvm# perl5.16.0 -sw BrowserUK_99133 +3.pl 3 9 4093 Took: 15.2425358295441 email7:/home/pyr/PRODUCTS/perl/perllvm# perllvm -sw BrowserUK_991333.p +l 3 9 4093 Took: 14.7814569950104 email7:/home/pyr/Git/FB# time perl5.16.0 FBtest.plx ## Start: VSZ-8008_KB-0 RSS-5108_KB-0 BLOCK: 2048/8/2048 ( 1,000,000 +) ... ## End: VSZ-50332 RSS-47468 Diff:42324|42360_KB-0 BLOCK: 2048 real 15m5.879s user 14m24.102s sys 0m38.442s email7:/home/pyr/Git/FB# time perllvm FBtest.plx ## Start: VSZ-8008_KB-0 RSS-5108_KB-0 BLOCK: 2048/8/2048 ( 1,000,000 +) ... ## End: VSZ-50332 RSS-47468 Diff:42324|42360_KB-0 BLOCK: 2048 real 15m33.238s user 14m45.243s sys 0m41.359s

In summary it doesn't look great yet, but I didn't use the JIT LLVM. You need to modify the Perl source to take advantage of it, and that will be another post.

Thank you

"Well done is better than well said." - Benjamin Franklin

Comment on perllVm: A Linux test of how Perl and LLVM would work together.
Select or Download Code
Re: perllVm: A Linux test of how Perl and LLVM would work together.
by Will_the_Chill (Pilgrim) on Sep 06, 2012 at 21:05 UTC
    Way to go, flexvault! *high five*
Re: perllVm: A Linux test of how Perl and LLVM would work together.
by BrowserUk (Pope) on Sep 06, 2012 at 21:57 UTC

    Nice one!++

    Could you explain real    15m5.879s? Cos that seems to say that it took 15 minutes 5.879 seconds, to run script that timed itself at 15.24 seconds?

    I looked at the man page but it is as clear as mud.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    RIP Neil Armstrong

      BrowserUk,

      Sometimes the best way is an example:

      time perllvm -sw BrowserUK_991333.pl 3 9 4093 Took: 14.9486489295959 real 0m15.143s user 0m14.981s sys 0m0.164s

      To execute your test-case, 'real' should also include the time to load and execute the LLVM Perl ( perllvm ) as well as the compile time of the script and then the execution and any wait time and exit. So 'real' is all inclusive, It's a easy way to find the total time of any *nix command. 'user' is the time perllvm was executing and 'sys' is the time that system resources ( including loading and executing ) was used.
      Note: In pseudo Perl ( untested )

      'real' >= 'user' + 'sys'; # approximately :-)

      Your test-case was cpu intensive, while my test-case did a lot of I/O. ( 1_000_000 random writes, 1_000_000 reads forward, and 1_000_000 reads backward ). But as you can see, it still was cpu intensive.

      time perllvm -E '$in = <>;' real 0m5.609s user 0m0.008s sys 0m0.004s
      With this I just counted to 5 and hit return. In this case, 'real' is wall clock time.

      Regards...Ed

      "Well done is better than well said." - Benjamin Franklin

      BrowserUk,

      I have regenerated 'perllvm' a couple of times, the most recent with '-O3' for the compiler flags, and it seems to be about 15% faster on your code. I put a 'for (0..8)' around the actual calls, and it seems that improvement gets better for the first 4 iterations, but don't know if 'jit' is working or not. '-O3' had no effect for my testcase, but I think the I/O wouldn't change much.

      perllvm -sw BrowserUK_991333.pl 3 9 4093 Took: 13.2621982097626 4093 Took: 12.8998439311981 4093 Took: 12.8468470573425 4093 Took: 12.8413920307159 4093 Took: 12.8571419715881 4093 Took: 12.8411600494385 4093 Took: 12.850515127182 4093 Took: 12.8421239757538 4093 Took: 12.8547790050507

      When I ran with the 'gcc' Perl there wasn't any major changes for each loop. I think 15% shouldn't be ignored by just compiling with 'clang' and '-O3'. I joined the LLVM developers list, and hope they are patient :-)

      Regards...Ed

      "Well done is better than well said." - Benjamin Franklin

        ... but don't know if 'jit' is working or not.

        If I understand what you did, it's not, and it's not going to work. You compiled Perl 5 as a C program with a C compiler (clang) to a native binary, and you used that to run Perl 5 code as Perl 5 code.

        Unless I missed a flag somewhere that used clang to compile Perl 5 into a native binary which is a thin shim around the LLVM JIT library and a bunch of bitcode that's the real output from the compiler, you're not going to get any LLVM JIT for the Perl 5 VM itself.

        You're definitely not going to JIT the Perl 5 code for the Ackermann function itself because nothing translates that to LLVM bitcode and feeds it to the LLVM JIT.

        I don't mean to keep ranting about this, but it seems like a lot of people think that LLVM is a magic wand you can wave over a program and magically get a JIT and concomitant orders of magnitude performance improvements. clang is a C compiler, like gcc. If you use clang like gcc, you get the same kind of thing you'll get from gcc.

        By no means should anyone sneer at a few percentage points improvement from clang optimizations versus gcc optimizations, especially LTO, but you're not getting orders of magnitude improvement without a lot more work.

        flexvault. Whilst 15% probably equals as much as p5p have succeeded in clawing back since 5.6.1, if that is all that is available, then the additional complexity of adding LLVM toolchain and its dependencies to the mix isn't worth it for your average perl user and certainly not for p5p -- given the possibilities of per platform problems with the switch from gcc to llvm.

        For example, I've spent the week getting changes made to the llvm emitter, to fix up incompatibilities between its .o representation and the MS 64-bit ABI. (To their credit, once I'd figured out the right approach and danced their tune by fulfilling their SOP, they had a patch which fixed the problem within a couple of hours. They are a very impressive bunch of developers and nice guys to boot.)

        I've also had my work cut out tracking down a stack dump in their front-end. The source turn out to be a (known) bug in the 64-bit version of the MS STL. But the most impressive bit of the experience, is that the stack trace that the debug version of their tool-set produced when the problem (an assertion failure inside the STL) occured, led me directly to the line&offset in the LLVM source where the problem arose. For now, a hand-coded function substituted for the failing STL routine gets me moving along.

        But using LLVM as an alternative C compiler was never going to be enough to warrant the effort. For a start, you do not get JIT from llvm without making changes to the project (Perl) code-base.

        For JIT to work, you have to:

        1. link the LLVM JIT engine into the Perl binary.
        2. convert the perl program being run into LLVM IR at runtime and feed it to that engine.

        That is not a transparent -- compile with llvm and get JIT -- automated procedure. It requires (possibly substantial) changes to the perl sources. This is why I isolated the sources required to build the perl executable binaries from the rest of the perl infrastructure.

        The (my) idea is to have a process that takes a new perl distribution, sucks out the smallest number of files possible from it, applies LLVM to them and builds versions of perl.exe perl516.dll/.so that they inter-operate with the rest of the standard perl distribution; .pms, XS an'all.

        Of course, that breaks the next time p5p break binary compatibility -- about once every 3 days lately -- but if enough gains can be demonstrated in this way -- I don't yet know how much that would need to be? 200%? -- then it might then encourage dialogue, even active participation.

        But if not, for those people for whom this is important, the extra work of installing LLVM and a process to produce this alternative binary compatible "fast Perl" would be worth it. (And, for windows at least, making that alternative binary available as a 'plug-in' to a standard binary distribution can make it available more widely.)

        And if it meant trailing the latest version of perl, and only catching up every 2 or 3 or 5, p5p distributions, that would be okay. There has been very little new that I've missed since the addition of defined-OR in 5.10; and quite a lot -- like smart-matching, use Switch; those funny arrays as hashes that came and went; etc. -- that I've actively avoided from the get-go, that are now deprecated or seem likely to disappear before too soon. (I don't even use 'say' because they screwed up the implementation and -l is just easier to turn on and off.)

        As I've been saying from the start of this, I don't think that LLVM as an 'alternative C compiler' alone is ever going to produce viable benefits for the masses. The addition of llvm JIT to perl will require a substantial effort that will include (amongst other things) the splitting of the perl5x.dll into 2 or 3 seperate binaries such that the 'immutable' bits of perl -- those that define Perl -- can remain unchanged, whilst the potentially mutable bits -- the compiled representation and the runloop -- become accessible.

        I also think that there is substantial potential in using the LLVM tool-sets profiling and tracing capabilities to 'zoom in' on particular areas of the perl code-base and highlight source-level changes that could be applied (by p5p), to good effect for the entire Perl community.

        It is most interesting to go through the exercise of compiling selected pieces of perl source to LLVM IR and then back to C. The results are, as machine generated source code is apt to be, pretty unreadable. but by looking at small pieces in isolation and comparing it back to the input, it is possible to see the potential of small changes in the existing sources that could have substantial affects.

        An old adage goes: a job started is a job half done; and another that says: the first step is the hardest. And yet another: there is a time when the talking must stop.

        As a first step, the ability to get 15% (and substantially faster build times if my experience is anything to go by), for nothing more than using a different compiler is nothing to be sneezed at.

        But it is only the first step. The potential is all in what comes next -- and that is only limited by the imaginations of the doers, not the nay-sayers.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        RIP Neil Armstrong

Re: perllVm: A Linux test of how Perl and LLVM would work together.
by Anonymous Monk on Sep 07, 2012 at 01:52 UTC
    Please ... take this ongoing discussion somewhere else more appropriate. This is not a meditation. There are plenty of other P5 development groups out there to choose from.

      Meditation is entirely appropriate place for this

      Oh, and STFU already

Re: perllVm: A Linux test of how Perl and LLVM would work together.
by Anonymous Monk on Sep 07, 2012 at 02:43 UTC

    you need to add '--enable-assertions=NO' because LLVM is built in debug mode by default.

    You can write that as --disable-assertions

      AM,

      Made the change to the OP.

      "Well done is better than well said." - Benjamin Franklin

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://992174]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (13)
As of 2014-08-27 15:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (242 votes), past polls