How to add CFLAGS to RVM? - rvm

I want to compile ruby-2.7.1. But I don't want override the system's ruby 2.7.1 because a lot of packages depends on Ruby.
So my easiest choice is RVM. But I want to compile Ruby natively because I will never need to copy the binary to another system. Is there a way to append -O3, -march=native, and -mtune=native option to CFLAGS?

So I ended up using:
CC=gcc HOSTCC=gcc CFLAGS="-O3 -pipe -fno-plt -march=native -mtune=native" CXXFLAGS="-O3 -pipe -fno-plt -march=native -mtune=native" .rvm/bin/rvm install ruby-2.7.1
To check (after compilation):
~/.rvm/rubies/ruby-2.7.1/bin/ruby -e "puts RbConfig::CONFIG.then { |x| [x['CFLAGS'], x['CXXFLAGS']] }"
Output should be similar to this:
-O3 -pipe -fno-plt -march=native -mtune=native -fPIC
-O3 -pipe -fno-plt -march=native -mtune=native
I did a Benchmark And I got a Tiny Performance Boost:
def prime(range)
(numbers = (2..range).to_a.unshift(nil, nil)).each do |num|
next if num.nil?
return numbers.compact if (sqr = num ** 2) > range
sqr.step(range, num) { |x| numbers[x] = nil }
end
end
def pi(n)
q, r, t, k, m, x, str = 1, 0, 1, 1, 3, 3, ''
if 4 * q + r - t < m * t
str.concat(m.to_s)
q, r, m = 10 * q, 10 * (r - m * t), (10 * (3 * q + r)) / t - 10 * m
else
q, r, t, k, m, x = q * k, (2 * q + r) * x, t * x, k + 1, (q * (7 * k + 2) + r * x) / (t * x), x + 2
end while str.length < n
str[1, 0] = '.'
str
end
puts "Calculating prime numbers"
total_time = 0
10.times do
time = Time.now
prime(5_000_000)
t = Time.now - time
puts "Time taken: #{t} s"
total_time += t
end
puts "Total time: #{total_time}\nCalculating digits of pi"
total_time = 0
5.times do
time = Time.now
pi(3000)
t = Time.now - time
puts "Time taken: #{t} s"
total_time += t
end
puts "Total time: #{total_time}"
Output:
Ruby 2.7.1-3 (generic x64) (compiled by Archlinux community):
Calculating prime numbers
Time taken: 0.875989347 s
Time taken: 0.867194701 s
Time taken: 0.888623001 s
Time taken: 0.896203257 s
Time taken: 0.878371141 s
Time taken: 0.870071403 s
Time taken: 0.885831722 s
Time taken: 0.893377101 s
Time taken: 0.878395115 s
Time taken: 0.869960278 s
Total time: 8.804017066
Calculating digits of pi
Time taken: 0.789893805 s
Time taken: 0.77520548 s
Time taken: 0.775608948 s
Time taken: 0.775225198 s
Time taken: 0.774519429 s
Total time: 3.8904528600000003
Ruby 2.7.1 (native, x64) (compiled now):
Calculating prime numbers
Time taken: 0.784012172 s
Time taken: 0.77873184 s
Time taken: 0.794907106 s
Time taken: 0.804767279 s
Time taken: 0.784964685 s
Time taken: 0.779715785 s
Time taken: 0.795503235 s
Time taken: 0.803209593 s
Time taken: 0.785618289 s
Time taken: 0.77906647 s
Total time: 7.890496454000001
Calculating digits of pi
Time taken: 0.794860247 s
Time taken: 0.768611289 s
Time taken: 0.77029717 s
Time taken: 0.753028667 s
Time taken: 0.752961357 s
Total time: 3.83975873
During the benchmark, I used the same terminal, no GUI processes running. I did the benchmarks at 4 - 5 seconds interval. I can confirm the same output even if I run the tests again and again.

Related

How can I solve a log2N question where input size is doubled?

A method is O(Nlog2N). It takes .001 seconds for the method to run when N = 1,000.
What is the expected time for the method to run when N = 2,000?
I know the answer to the question is approximately 0.0022, but I don't know how to reach that answer. Can someone help with this?
Since C(1000)=.001 and C(N) ~ k Nlog2N => k ~ .001 / (1000 * 10) ~ 1e-7
So C(2000) ~ 1e-7 * (2000 * 11) ~ .0022

Optim.jl univariate bounded optimization confusing output when using Inf as bound

The following is a self-contained example illustrating my problem.
using Optim
χI = 3
ψI = 0.5
ϕI(z) = z^-ψI
λ = 1.0532733
V0 = 0.8522423425
zE = 0.5986
wRD = 0.72166623555
objective1(z) = -(z * χI * ϕI(z + zE) * (λ-1) * V0 - z * ( wRD ))
objective2(z) = -1 * objective1(z)
lower = 0.01
upper = Inf
plot(0:0.01:0.1,objective1,title = "objective1")
png("/home/nico/Desktop/objective1.png")
plot(0:0.01:0.1,objective2, title = "objective2")
png("/home/nico/Desktop/objective2.png")
results1 = optimize(objective1,lower,upper)
results2 = optimize(objective2,lower,upper)
The plots are
and
Both objective1(z) and objective2(z) return NaN at z = 0 and finite values everywhere else, with an optimum for some z > 0.
However the output of results1 is
Results of Optimization Algorithm
* Algorithm: Brent's Method
* Search Interval: [0.010000, Inf]
* Minimizer: Inf
* Minimum: NaN
* Iterations: 1000
* Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): false
* Objective Function Calls: 1001
and the output of results2 is
Results of Optimization Algorithm
* Algorithm: Brent's Method
* Search Interval: [0.010000, Inf]
* Minimizer: Inf
* Minimum: NaN
* Iterations: 1000
* Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): false
* Objective Function Calls: 1001
I believe the problem is with upper = Inf. If I change that to upper = 100, for example, the output of results1 is
Results of Optimization Algorithm
* Algorithm: Brent's Method
* Search Interval: [0.010000, 100.000000]
* Minimizer: 1.000000e-02
* Minimum: 5.470728e-03
* Iterations: 55
* Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): true
* Objective Function Calls: 56
and results2 returns
Results of Optimization Algorithm
* Algorithm: Brent's Method
* Search Interval: [0.010000, 100.000000]
* Minimizer: 1.000000e+02
* Minimum: -7.080863e+01
* Iterations: 36
* Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): true
* Objective Function Calls: 37
as expected.
As you note in your question - you use bounded optimization algorithm but you pass an unbounded interval to it.
Citing the documentation (https://julianlsolvers.github.io/Optim.jl/latest/#user/minimization/), which is precise about it the optimize function is for Minimizing a univariate function on a bounded interval.
To give a more detail about the problem you encounter. The optimize method searches points inside your interval. There are two algorithms implemented: Brent (the default) and Golden Section. The point they first check is:
new_minimizer = x_lower + golden_ratio*(x_upper-x_lower)
and you see that it new_minimizer will be Inf. So the optimization routine is not even able to find a valid interior point. Then you see that your functions return NaN for Inf argument:
julia> objective1(Inf)
NaN
julia> objective2(Inf)
NaN
This combined gives you explanation why the minimum found is Inf and the objective is NaN in the produced output.
The second point is that you should remember that Float64 numbers have a finite precision, so you should choose the interval so as to make sure that the method is actually able to accurately evaluate the objective in it. For example even this fails:
julia> optimize(objective1, 0.0001, 1.0e308)
Results of Optimization Algorithm
* Algorithm: Brent's Method
* Search Interval: [0.000100, 100000000000000001097906362944045541740492309677311846336810682903157585404911491537163328978494688899061249669721172515611590283743140088328307009198146046031271664502933027185697489699588559043338384466165001178426897626212945177628091195786707458122783970171784415105291802893207873272974885715430223118336.000000]
* Minimizer: 1.000005e+308
* Minimum: -Inf
* Iterations: 1000
* Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): false
* Objective Function Calls: 1001
The reason is that objective1 actually starts to behave in a numerically unstable way for very large arguments (because it has a finite precision), see:
julia> objective1(1.0e307)
7.2166623555e306
julia> objective1(1.0e308)
-Inf
The last point is that actually Optimize tells you that something went wrong and you should not rely on the results as:
julia> results1.converged
false
julia> results2.converged
false
For the initial specification of the problem (with Inf).

Computing pi through series summation in Fortran

Note: LaTeX isn't supported on this site. I'm not sure if there is a better way to write math equations other than to write them in code.
I'm writing a Fortran program to estimate pi through the summation of series:
A = Sum of a_i from i=1 to N
where
pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + 1/13 ...
To compute pi through the series summation, the suggested approach is to set
a_i = (-1)^(i+1)/(2i-1)
To do this, I wrote the following Fortran program -
program cpi
double precision val, pi
integer i
num = 1000
val = 0
do i = 1, num
val = val + ((-1)**(i+1))/(2*i-1)
end do
pi = val
print *, 'Estimated Value of PI:', pi
end program cpi
When I run this program, the output is
Estimated Value of PI: 1.0000000000000000
I must have made a mistake (likely in the /(2*i-1)). I new to Fortran and don't know what I did wrong.
I see my mistake! I need to write out 1.d0 and 2.d0 instead of 1 and 2 so that the calculations are evaluated in double format. I also forgot to multiply pi = val*4.d0. Changing the cpi program to
program cpi
double precision val, pi, MFLOPS
integer i, T1, T2
num = 1000000
val = 0.d0
call system_clock(T1) ! get time stamp
do i = 1, num
val = val + ((-1.d0)**(i+1.d0))/(2.d0*i-1.d0)
end do
call system_clock(T2) ! get time stamp
MFLOPS = num*2.d0/((T2-T1)*1.d8) ! compute MFlop/sec rate
pi = val*4.d0
print *, 'Estimated Value of PI:', pi
print *, 'The calculated number of MFLOPS is:', MFLOPS
end program cpi
returns
Estimated Value of PI: 3.1415916535897743
The calculated number of MFLOPS is: 3.0303030303030304E-002
I also added a MFLOPS calculation to see the computational speed.

Why Fortran is slow in the julia benchmark "rand_mat_mul"?

Benchmark test results on the home page of Julia (http://julialang.org/) shows that Fortran is about 4x slower than Julia/Numpy in the "rand_mat_mul" benchmark.
I can not understand that why fortran is slower while calling from the same fortran library (BLAS)??
I have also performed a simple test for matrix multiplication evolving fortran, julia and numpy and got the similar results:
Julia
n = 1000; A = rand(n,n); B = rand(n,n);
#time C = A*B;
>> elapsed time: 0.069577896 seconds (7 MB allocated)
Numpy in IPython
from numpy import *
n = 1000; A = random.rand(n,n); B = random.rand(n,n);
%time C = dot(A,B);
>> Wall time: 98 ms
Fortran
PROGRAM TEST
IMPLICIT NONE
INTEGER, PARAMETER :: N = 1000
INTEGER :: I,J
REAL*8 :: T0,T1
REAL*8 :: A(N,N), B(N,N), C(N,N)
CALL RANDOM_SEED()
DO I = 1, N, 1
DO J = 1, N, 1
CALL RANDOM_NUMBER(A(I,J))
CALL RANDOM_NUMBER(B(I,J))
END DO
END DO
call cpu_time(t0)
CALL DGEMM ( "N", "N", N, N, N, 1.D0, A, N, B, N, 0.D0, C, N )
call cpu_time(t1)
write(unit=*, fmt="(a24,f10.3,a1)") "Time for Multiplication:",t1-t0,"s"
END PROGRAM TEST
gfortran test_blas.f90 libopenblas.dll -O3 & a.exe
>> Time for Multiplication: 0.296s
I have changed the timing function to system_clock() and result turns out to be (I run it five times in one program)
Time for Multiplication: 92ms
Time for Multiplication: 92ms
Time for Multiplication: 89ms
Time for Multiplication: 85ms
Time for Multiplication: 94ms
It is approximate as Numpy, but still about 20% slower than Julia.

Lat Long to Minutes and Seconds?

Google Maps gives me the Lat and Long of a location in decimal notation like this:
38.203655,-76.113281
How do I convert those to Coords (Degrees, Minutes , Seconds)
38.203655 is a decimal value of degrees. There are 60 minutes is a degree and 60 seconds in a minute (1degree == 60min == 3600s).
So take the fractional part of the value, i.e. 0.203655, and multiply it with 60 to get minutes, i.e. 12.2193, which is 12 minutes, and then repeat for the fractional part of minutes, i.e. 0.2193 = 13.158000 seconds.
Example in python:
def deg_to_dms(deg):
d = int(deg)
md = abs(deg - d) * 60
m = int(md)
sd = (md - m) * 60
return [d, m, sd]
print deg_to_dms(38.203655)
print deg_to_dms(-76.113281)
In case you need other geo-related functionality in JavaScript, you may use the following library
http://www.movable-type.co.uk/scripts/latlong.html
it provides the following functionality:
DMS from/to decimal latitude/longitude conversions
Distance calculations
Bearing calculation
Intersection point calcualtion
Python library that does the trick:
https://pypi.python.org/pypi/LatLon/1.0.2
I think this will help you with the solution :
def deg_min_sec(self,degrees=0.0):
if type(degrees) != 'float':
try:
degrees = float(degrees)
except:
print '\nERROR: Could not convert %s to float.' % (type(degrees))
return 0
minutes = degrees % 1.0 * 60
seconds = minutes % 1.0 * 60
return (degrees, minutes, seconds)