[前][次][番号順一覧][スレッド一覧]

ruby-changes:54466

From: mrkn <ko1@a...>
Date: Tue, 1 Jan 2019 21:20:09 +0900 (JST)
Subject: [ruby-changes:54466] mrkn:r66681 (trunk): complex.c: Optimize Complex#+ for some conditions

mrkn	2019-01-01 21:20:05 +0900 (Tue, 01 Jan 2019)

  New Revision: 66681

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66681

  Log:
    complex.c: Optimize Complex#+ for some conditions
    
    Optimize f_add defined in complex.c for some specific conditions.
    It makes Complex#+ about 1.4x faster than r66678.
    
    Compared to r66678:
    
    ```
    mrkn-mbp15-late2016:complex-optim-o3 mrkn$ make benchmark ITEM=complex_float_ COMPARE_RUBY=/Users/mrkn/.rbenv/versions/trunk-o3/bin/ruby
    /Users/mrkn/src/github.com/ruby/ruby/revision.h unchanged
    /Users/mrkn/.rbenv/shims/ruby --disable=gems -rrubygems -I/Users/mrkn/src/github.com/ruby/ruby/benchmark/lib /Users/mrkn/src/github.com/ruby/ruby/benchmark/benchmark-driver/exe/benchmark-driver \
                        --executables="compare-ruby::/Users/mrkn/.rbenv/versions/trunk-o3/bin/ruby -I.ext/common --disable-gem" \
                        --executables="built-ruby::./miniruby -I/Users/mrkn/src/github.com/ruby/ruby/lib -I. -I.ext/common  -r/Users/mrkn/src/github.com/ruby/ruby/prelude --disable-gem" \
                        $(find /Users/mrkn/src/github.com/ruby/ruby/benchmark -maxdepth 1 -name '*complex_float_*.yml' -o -name '*complex_float_*.rb' | sort)
    Calculating -------------------------------------
                         compare-ruby  built-ruby
       complex_float_add       9.132M     12.864M i/s -      1.000M times in 0.109511s 0.077734s
       complex_float_div     600.723k    627.878k i/s -      1.000M times in 1.664662s 1.592666s
       complex_float_mul       2.320M      2.347M i/s -      1.000M times in 0.431039s 0.426113s
       complex_float_new       1.473M      1.489M i/s -      1.000M times in 0.678791s 0.671750s
     complex_float_power       1.690M      1.722M i/s -      1.000M times in 0.591863s 0.580775s
       complex_float_sub       8.870M      9.516M i/s -      1.000M times in 0.112740s 0.105091s
    
    Comparison:
                    complex_float_add
              built-ruby:  12864383.7 i/s
            compare-ruby:   9131502.8 i/s - 1.41x  slower
    
                    complex_float_div
              built-ruby:    627878.0 i/s
            compare-ruby:    600722.5 i/s - 1.05x  slower
    
                    complex_float_mul
              built-ruby:   2346795.3 i/s
            compare-ruby:   2319975.7 i/s - 1.01x  slower
    
                    complex_float_new
              built-ruby:   1488649.1 i/s
            compare-ruby:   1473207.5 i/s - 1.01x  slower
    
                  complex_float_power
              built-ruby:   1721837.2 i/s
            compare-ruby:   1689580.2 i/s - 1.02x  slower
    
                    complex_float_sub
              built-ruby:   9515562.7 i/s
            compare-ruby:   8869966.3 i/s - 1.07x  slower
    ```

  Modified files:
    trunk/complex.c
    trunk/internal.h
    trunk/numeric.c
    trunk/test/ruby/test_complex.rb
Index: complex.c
===================================================================
--- complex.c	(revision 66680)
+++ complex.c	(revision 66681)
@@ -75,6 +75,20 @@ f_add(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/complex.c#L75
 	return x;
     if (FIXNUM_ZERO_P(x))
 	return y;
+
+    if (RB_INTEGER_TYPE_P(x) &&
+        UNLIKELY(rb_method_basic_definition_p(rb_cInteger, idPLUS))) {
+      return rb_int_plus(x, y);
+    }
+    else if (RB_FLOAT_TYPE_P(x) &&
+             UNLIKELY(rb_method_basic_definition_p(rb_cFloat, idPLUS))) {
+      return rb_float_plus(x, y);
+    }
+    else if (RB_TYPE_P(x, T_RATIONAL) &&
+             UNLIKELY(rb_method_basic_definition_p(rb_cRational, idPLUS))) {
+      return rb_rational_plus(x, y);
+    }
+
     return rb_funcall(x, '+', 1, y);
 }
 
Index: internal.h
===================================================================
--- internal.h	(revision 66680)
+++ internal.h	(revision 66681)
@@ -1655,6 +1655,7 @@ VALUE rb_int_pred(VALUE num); https://github.com/ruby/ruby/blob/trunk/internal.h#L1655
 VALUE rb_int_uminus(VALUE num);
 VALUE rb_float_uminus(VALUE num);
 VALUE rb_int_plus(VALUE x, VALUE y);
+VALUE rb_float_plus(VALUE x, VALUE y);
 VALUE rb_int_minus(VALUE x, VALUE y);
 VALUE rb_int_mul(VALUE x, VALUE y);
 VALUE rb_int_idiv(VALUE x, VALUE y);
Index: numeric.c
===================================================================
--- numeric.c	(revision 66680)
+++ numeric.c	(revision 66681)
@@ -1018,8 +1018,8 @@ rb_float_uminus(VALUE flt) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1018
  * Returns a new Float which is the sum of +float+ and +other+.
  */
 
-static VALUE
-flo_plus(VALUE x, VALUE y)
+VALUE
+rb_float_plus(VALUE x, VALUE y)
 {
     if (RB_TYPE_P(y, T_FIXNUM)) {
 	return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
@@ -5674,7 +5674,7 @@ Init_Numeric(void) https://github.com/ruby/ruby/blob/trunk/numeric.c#L5674
     rb_define_alias(rb_cFloat, "inspect", "to_s");
     rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
     rb_define_method(rb_cFloat, "-@", rb_float_uminus, 0);
-    rb_define_method(rb_cFloat, "+", flo_plus, 1);
+    rb_define_method(rb_cFloat, "+", rb_float_plus, 1);
     rb_define_method(rb_cFloat, "-", flo_minus, 1);
     rb_define_method(rb_cFloat, "*", flo_mul, 1);
     rb_define_method(rb_cFloat, "/", flo_div, 1);
Index: test/ruby/test_complex.rb
===================================================================
--- test/ruby/test_complex.rb	(revision 66680)
+++ test/ruby/test_complex.rb	(revision 66681)
@@ -269,6 +269,36 @@ class Complex_Test < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L269
     assert_equal(Complex(Rational(5,3),Rational(2)), c + Rational(2,3))
   end
 
+  def test_add_with_redefining_int_plus
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Integer
+        def +(other); 42; end
+      end
+      a = Complex(1, 2) + Complex(0, 1)
+      puts a == Complex(1, 42)
+    end;
+  end
+
+  def test_add_with_redefining_float_plus
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Float
+        def +(other); 42.0; end
+      end
+      a = Complex(1, 2.0) + Complex(0, 1)
+      puts a == Complex(1, 42.0)
+    end;
+  end
+
+  def test_add_with_redefining_rational_plus
+    assert_in_out_err([], <<-'end;', ['true'], [])
+      class Rational
+        def +(other); 355/113r; end
+      end
+      a = Complex(1, 2r) + Complex(0, 1)
+      puts a == Complex(1, 355/113r)
+    end;
+  end
+
   def test_sub
     c = Complex(1,2)
     c2 = Complex(2,3)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]