-
Notifications
You must be signed in to change notification settings - Fork 186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serious performance regression for method pow(a, m) #3544
Comments
Thank you for reporting the issue! Could you please share your benchmarking results? |
Which version of TruffleRuby are you using? Related: #1999
But always convert to BigInteger, maybe that's the overhead? If that's the case we could use similar logic to CRuby/JRuby for the small integers cases, but would be good to make sure that's the issue and how much slower it is before importing that code. |
First code correction.
Here are times on my system for Ruby 3.3 w/wo YJIT, JRuby 9.4.6.0 and TruffleRuby 24.0.0, via rvm.
|
With a slightly modified script which:
require 'benchmark'
# Enable YJIT if using CRuby >= 3.3"
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
puts RUBY_DESCRIPTION
def modinv(a0, m0)
return 1 if m0 == 1
a, m = a0, m0
x0, inv = 0, 1
while a > 1
inv -= (a / m) * x0
a, m = m, a % m
x0, inv = inv, x0
end
inv += m0 if inv < 0
inv
end
def modinv1(r, m)
inv = r
while (r * inv) % m != 1; inv %= m; inv *= r end
inv % m
end
def modinv2(r, m)
inv = r
while (r * inv) % m != 1; inv = (inv * r) % m end
inv % m
end
def modinv3(r, m, rescnt)
(r ** (rescnt-1)) % m
end
def modinv4(r, m, rescnt)
r.pow(rescnt-1, m)
end
def tm(&b)
puts
3.times do
puts Benchmark.realtime(&b)
end
end
resp7 = [11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,
97,101,103,107,109,113,121,127,131,137,139,143,149,151,157,163,
167,169,173,179,181,187,191,193,197,199,209,211]
print resp7.map { |r| modinv(r, 210) }
puts
print resp7.map { |r| modinv1(r, 210) }
puts
print resp7.map { |r| modinv2(r, 210) }
puts
print resp7.map { |r| modinv3(r, 210, 48) }
puts
print resp7.map { |r| modinv4(r, 210, 48) }
puts
tm{ 100000.times {resp7.each { |r| modinv(r, 210) } } }
tm{ 100000.times {resp7.each { |r| modinv1(r, 210) } } }
tm{ 100000.times {resp7.each { |r| modinv2(r, 210) } } }
tm{ 100000.times {resp7.each { |r| modinv3(r, 210, 48) } } }
tm{ 100000.times {resp7.each { |r| modinv4(r, 210, 48) } } } I get:
I noticed YJIT is much slower in my measurements, maybe you are on a different architecture, I guess darwin-aarch64? But overall it's similar results, TruffleRuby is fastest everywhere except for the last method, Either way |
@andrykonchin Could you port https://github.com/jruby/jruby/blob/9.4.4.0/core/src/main/java/org/jruby/RubyInteger.java#L935-L944 to TruffleRuby? (or from CRuby, but probably more work) |
My system is a Lenovo Legion Slimjet laptop (2022), AMD Ryzen 9 5900HX, with Linux. The issue is that |
Fixed in #3552 Now
As a bonus the new code is written in Ruby (which in this case is a lot faster than Java's |
The code below shows this issue.
On Truffleruby, using
pow(a, m)
is orders of magnitude slower than on [C|J]Ruby, where it's the fastest.The text was updated successfully, but these errors were encountered: