Recently in RubyInline Category

Ruby Inline is an analog to Perl's Inline::C. Out of the box, it allows you to embed C/++ external module code in your ruby script directly. By writing simple builder classes, you can teach how to cope with new languages (fortran, perl, whatever). The code is compiled and run on the fly when needed.

Using the package_inline tool Inline allows you to package up your inlined object code for distribution to systems without a compiler.

Changes:

3.6.7 / 2008-03-20

Ruby Inline is an analog to Perl's Inline::C. Out of the box, it allows you to embed C/++ external module code in your ruby script directly. By writing simple builder classes, you can teach how to cope with new languages (fortran, perl, whatever). The code is compiled and run on the fly when needed.

Changes:

3.6.6 / 2007-12-27* 1 minor enhancement:

Ruby Inline is an analog to Perl's Inline::C. Out of the box, it allows you to embed C/++ external module code in your ruby script directly. By writing simple builder classes, you can teach how to cope with new languages (fortran, perl, whatever). The code is compiled and run on the fly when needed.

Changes:

3.6.5 / 2007-11-08

Ruby Inline is an analog to Perl's Inline::C. Out of the box, it allows you to embed C/++ external module code in your ruby script directly. By writing simple builder classes, you can teach how to cope with new languages (fortran, perl, whatever). The code is compiled and run on the fly when needed.

Changes:

3.6.4 / 2007-08-20

Ruby Inline is an analog to Perl's Inline::C. Out of the box, it allows you to embed C/++ external module code in your ruby script directly. By writing simple builder classes, you can teach how to cope with new languages (fortran, perl, whatever). The code is compiled and run on the fly when needed.

3.6.3 / 2007-04-27

  • 7 minor enhancements:

    • Added maprubyconst and mapcconst to C builder.
    • Converted example.rb to a real benchmark setup.
    • Improved error messages.
    • Added options hash for all C builder methods.
    • Options hash can take optional :method_name param to have ruby name diff from c.
    • Converted to a more traditional setup. Now I can heckle!
    • Cleaned up ruby.h search.
  • 2 bug fixes:

    • Added CCDLFLAGS. Should pick up -fPIC on misconfigured 64 bit machines.
    • Broke up all warnings so progress report was cleaner.

InlineFortran 1.0.0 Released

| | Comments (0)

InlineFortran version 1.0.0 has been released!

http://www.rubyforge.org/projects/rubyinline

FEATURES/PROBLEMS:

  • Very rudimentary right now. Needs some love.

SYNOPSYS:

inline :Fortran do |builder|
  builder.subroutine('print_integer', ["void", "int"], <<-END)
    subroutine print_integer( integer )
      integer, intent(in) :: integer
      print *, 'integer: ', integer
    end
  END
end

Changes:

1.0.0 / 2006-10-21

  • 1 major enhancement
    • Birthday!

http://www.rubyforge.org/projects/rubyinline

RubyInline 3.6.2 Released

| | Comments (0)

RubyInline version 3.6.2 has been released! This is a quick patch for weird versions of GCC and/or linux and makes ParseTree work again on (hopefully) everything under the sun.

Ruby Inline is an analog to Perl's Inline::C. Out of the box, it allows you to embed C/++ external module code in your ruby script directly. By writing simple builder classes, you can teach how to cope with new languages (fortran, perl, whatever). The code is compiled and run on the fly when needed.

% sudo gem update RubyInline

Changes:

3.6.2 / 2006-10-12

  • 2 bug fixes
    • comment stripper much more sane to fix problems on certain linux distros
    • fixed a nit with older C compilers.

4 releases went out the door

| | Comments (0)

I just finished releasing:

  • hoe 1.1.1
  • RubyInline 3.6.1
  • ParseTree 1.6.0
  • and new to the (official) family: ruby2ruby 1.1.0!
% sudo gem update hoe RubyInline ParseTree
% sudo gem install ruby2ruby

The biggies are:

  • ParseTree just got a major enema. 2k lines o' diff with an overall net loss of 800 loc. Awesome
  • ParseTree's new testing infrastructure is solid as all hell.
  • and it is circularly validated via ruby2ruby's tests.
  • We flushed out a bunch of completely unknown bugs by this process. About 6 nodes were broken in one way or another.

Also of note:

  • mingw32 patches for RubyInline
  • lots and lots of nice little bug fixes and enhancements all over.

Recursive Functions in RubyInline

| | Comments (2)

harrisj filed a bug against inline today regarding recursive functions failing. The simplest example is fibonacci. The problem is simple, and its solution (workaround really) is simple too. Let's dig in, shall we?

Pure Ruby

class Fib
  def rubyfib(n)
    return 1 if n <= 1
    rubyfib(n-1) + nfib(n-2)
  end
end

Simple enough example, but because of its recursive nature it takes a long time to run (less to do with its recursiveness than the simple fact of the matter that it is doing a ton of method dispatches in general.

Inline C

So, let's say that we have this code coming up at the top of our profile and we want to speed it up. We grab our trusty inline and pop in the equivalent in C:

require 'inline'
class Fib
  inline do |builder|
    builder.c <<-END
      long badfib(long n) {
        if (n <= 1) {
          return 1;
        } else {
          return badfib(n-1) + badfib(n-2);
        }
      }
    END
  end
end

The Recursion Problem

The problem is that this doesn't compile properly. Why? It looks right. Indeed it does, but you need to dig deeper to understand what inline is doing for you to make this stuff look so easy. What it is really generating is this:

static VALUE badfib(VALUE self, VALUE _n) {
  long n = NUM2INT(_n);

  if (n == 0 || n == 1) {
    return INT2NUM(1);
  } else {
    return INT2NUM(badfib(n-1) + badfib(n-2));
  }
}

The problem is twofold. badfib has two arguments, not one, and both of them are VALUE, not long. The "simple" solution is to pass in self, but you still have to convert the second arg as well and the return value. The last line starts to look gross:

  return FIX2INT(badfib(self, INT2FIX(n-1))) + FIX2INT(badfib(self, INT2FIX(n-2)));

That is icky. It works, is damn fast compared to the pure ruby example (14.5s vs 0.3s in my benchmarks), but it is still icky. I'll even take a speed hit to reduce icky. That said, there is a much simpler solution.

Pure C Recursion, Ruby Wrapper

Instead of mixing the two languages at that level (and it really is an oil and water problem at this stage--maybe if we shake it enough we'll get a vinaigrette), strictly separate them:

builder.prefix <<-END
  long realfib(long n) {
    if (n <= 1) {
      return 1;
    } else {
      return realfib(n-1) + realfib(n-2);
    }
  }
END

builder.c <<-END
  long cfib(long n) {
    return realfib(n);
  }
END

Here we've popped the real work into builder.prefix instead of builder.c which just injects the code raw. As a result, we have one layer doing ruby-to-c-to-ruby conversions and another doing the work. It is even faster because you get rid of all those icky conversions at every level. Even the resulting code looks much better:

long realfib(long n) {
  if (n <= 1) {
    return 1;
  } else {
    return realfib(n-1) + realfib(n-2);
  }
}

static VALUE cfib(VALUE self, VALUE _n) {
  long n = NUM2INT(_n);

  return INT2NUM(realfib(n));
}

Just one problem

There is one problem I want to point out here. Granted, the problem itself is slightly contrived, but I see examples like this coming up over and over in IRC and the mailing list. The problem is this: people get so myopically focused on using C to make things faster that they don't bother looking at their algorithms or data-structures. It is sad. Ruby may be slow for method dispatch, but bad code can be slow in ANY language. Wanna see a simple and readable pure ruby solution to the above that kicks the crap out of my fastest C solution?

##
# Classic fibonacci is boring, cache the hell out of it.
@@fib = {}
def fasterfib(n)
  return 1 if n <= 1
  unless @@fib.has_key? n then
    @@fib[n] = fasterfib(n-1) + fasterfib(n-2)
  end
  @@fib[n]
end

C doesn't make ruby fast. Avoiding method dispatch makes ruby fast. You can do that using pure ruby quite a bit of the time by applying your noodle. Check out the times:

% ./fib.rb 10000 15
# of iterations = 10000
                          user     system      total        real
null_time             0.000000   0.000000   0.000000 (  0.001779)
fib-ruby             14.450000   0.060000  14.510000 ( 14.628854)
badfib                0.310000   0.000000   0.310000 (  0.318015)
cfib                  0.150000   0.000000   0.150000 (  0.147117)
fib-cached            0.010000   0.000000   0.010000 (  0.012523)

And Zed, before you get started, I picked 10k because that was all I had the patience to sit through. This isn't a scientific writeup. So nyah!

RubyInline version 3.6.0 has been released! Only 10 month late! (ugh I can be so spacy sometimes!)

http://www.zenspider.com/ZSS/Products/RubyInline/
http://rubyforge.org/projects/rubyinline/

Description:

Ruby Inline is an analog to Perl's Inline::C. Out of the box, it
allows you to embed C/++ external module code in your ruby script
directly. By writing simple builder classes, you can teach how to cope
with new languages (fortran, perl, whatever). The code is compiled and
run on the fly when needed.

Using the package_inline tool Inline now allows you to package up
your inlined object code for distribution to systems without a
compiler (read: windows)!

Features/Problems:

+ Quick and easy inlining of your C or C++ code embedded in your ruby script.
+ Extendable to work with other languages.
+ Automatic conversion between ruby and C basic types
+ char, unsigned, unsigned int, char *, int, long, unsigned long
+ inline_c_raw exists for when the automatic conversion isn't sufficient.
+ Only recompiles if the inlined code has changed.
+ Pretends to be secure.
+ Only requires standard ruby libraries, nothing extra to download.
+ Can generate a basic Rakefile and package up built extensions for distribution.

http://www.zenspider.com/ZSS/Products/RubyInline/
http://rubyforge.org/projects/rubyinline/

Changes:

+ 6 minor enhancements
+ C builder can now be used directly for other foreign language glue.
+ Pretty much all (c) functions are plain argument style, not argc/argv.
+ Added Nathaniel and Dan's patches for windows support.
+ Added VALUE as a default known type.
+ Improved testing under $DEBUG.
+ Deprecated $INLINE_FLAGS and $INLINE_LIBS are dead.
+ 3 bug fixes
+ Fixed a number of issues wrt testing.
+ Cleaned up and cached certain calculations.
+ Some windows compiler fixes went in, but MS compiler is a PITA still.

http://www.zenspider.com/ZSS/Products/RubyInline/
http://rubyforge.org/projects/rubyinline/