Tag Archives: Julia

Why I Switched to Julia

By: Bradley Setzler

Re-posted from: http://juliaeconomics.com/2014/06/15/why-i-started-a-blog-about-programming-julia-for-economics/

The following story, which I originally posted to The COBE Blog, explains why I began programming in Julia. Since then, I have found that Julia improves the performance of my other econometric estimators. However, Julia has a major disadvantage in that it lacks informative documentation and tutorials, much less accumulated discussion on sites like stackoverflow. This blog is meant to record the skills I am learning in Julia over time, to serve as a tutorial for economists and others learning the Julia programming language.


Is Julia the Future of Computational Economics?

Jorge Luis Garcia and I are currently estimating a structural econometric model of game-theoretic parent-child interaction. Using the standard implementation of Python (the code is written entirely in NumPy and SciPy with data prepared by Pandas), the optimizer ran for 24 hours, then terminated due to the 5,000 iteration limit. It was converging smoothly, but never quite arrived.

While waiting for the estimates last night (and growing increasingly impatient), I installed Julia and its packages, learned how to program in Julia, rewrote the estimation in Julia, and this morning successfully optimized the likelihood in Julia.

The contrast is staggering: the optimization that didn’t converge after 24 hours in Python converged after only 15 minutes in Julia while Python was still running on the same processor. Julia was already achieving a greater likelihood than Python after only 5 minutes even though Python had a 20-hour head start. They are both using the same optimization algorithm (including numerical tolerance), and the structure of the code is identical. Julia evaluates the likelihood in 0.5 seconds, while Python requires 21 seconds per evaluation, so Julia is about 40 times faster in the function evaluation, and about 100 times faster in the optimizer (I’m giving Python the benefit of the doubt even though it never converged).

The final iteration of Python was approaching the Julia optimal likelihood and getting closer; the only difference was that Julia arrived much, much more quickly. Since my next step is to bootstrap the estimator, speed is extremely important. Some practical arithmetic: on my four-core laptop, it would take two-thirds of a year to bootstrap this estimator 1,000 times, whereas Julia could do it in fewer than three days (though I’m planning to run the bootstrap in batch on the server).

I am agnostic on programming languages; I use whatever gets the answer fastest and can be reproduced most clearly, and I often use multiple languages on the same project to get the best features of each. My only claim is that Julia has taken the Python code, with minimal syntax changes, and executed the code 100 times faster for someone who had no prior experience with Julia. This was not a contrived, time-testing code; this is the estimator motivated by economic theory. The 100-fold speed increase of Julia relative to Python has been found elsewhere in computational economics.

So, is Julia the programming language of the future in structural econometrics? I’m not sure, but it seems to dominate Python and R at the moment.


Bradley J. Setzler

 

Revisiting emulated OOP behaviour and multiple dispatch in Julia

By: Terence Copestake

Re-posted from: https://thenewphalls.wordpress.com/2014/06/02/revisiting-emulated-oop-behaviour-and-multiple-dispatch-in-julia/

In an earlier post, I explored one approach to emulating bundling functionality with the data on which it operates, akin to object methods in OOP languages such as C# and PHP. A comment posted by Matthew Browne questioned whether this approach was compatible with Julia’s multiple dispatch.

This is something I thought about at the time of writing the original article, but I had assumed it wouldn’t be possible due to the way in which the anonymous functions are assigned to variables i.e. assigning one definition would overwrite the previous. However, Matthew’s question prompted me to reconsider – and after some brief experimentation and some small alterations, I found that there is indeed a way to maintain compatibility with multiple dispatch.

Below is an updated example type definition:

type MDTest
    method::Function

    function MDTest()
        this = new()

        function TestFunction(input::String)
            println(input)
        end

        function TestFunction(input::Int64)
            println(input * 10)
        end

        this.method = TestFunction

        return this
    end
end

The theory is basically the same, with the constructor assigning the methods to their respective fields within the type. The difference is in how the functions are defined and assigned.

On lines 7 and 11, methods are defined with different argument types. These methods could be defined outside of the type definition without error, but defining them within the constructor has the advantage of not polluting the global scope.

On line 15, the function is assigned to its field using some slightly different syntax, which allows both methods to be called.

With this, the example code below:

test = MDTest()

test.method("String")

test.method(5)

Produces the output:

String
50

Another advantage to this approach is the absence of anonymous functions – which, according to benchmarks and GitHub issues, have significantly worse performance compared to named functions.

Julia versus R – Playing around

By: Alvaro "Blag" Tejada Galindo

Re-posted from: http://blagrants.blogspot.com/2014/05/julia-versus-r-playing-around.html

So…as time goes by, I’m getting more proficient with Julia…which is something fairly easy as the learning curve is pretty fast…

I decided to load a file with 590,209 records that I got from Freebase…the file in question contains Actors and Actresses from movies…you can have a quick look here…

For this test, I’m using my Linux box on VMWare running on 2 GB of RAM…running Ubuntu 12.04.4 (Precise)

For R, I’m not using any special package…just plain R…version 2.14.1 and for Julia version 0.2.1, I’m using the DataFrames package…

Let’s take a look at the R source code first along with its runtime processing…

Actors_Info.R
start.time <- Sys.time()
if(!exists("Actors")){
Actors<-read.csv("Actors_Table.csv", header=TRUE, 
                     stringsAsFactors=FALSE, colClasses="character", na.strings = "")
}
Actors<-unique(Actors)
Actors<-Actors[complete.cases(Actors),]
Actor_Info<-data.frame(Actor_Id=Actors$Actor_Id,Name=Actors$Name,Gender=Actors$Gender)
Actor_Info<-Actor_Info[order(Actor_Info$Gender),]
write.csv(Actor_Info,"Actor_Info_R.csv",row.names=TRUE)
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken

This source will first ask if the file was loaded already, if not…it will load it…then, it will eliminate the repeated records, delete all the null or NA’s and the create a new Data Frame, sort it by “Gender” and then write a new CSV file…time will be taken to measure its speed…we will run it twice…first time the file is not loaded…second time it will…and that should improve greatly the execution time…

As we can see…the times are really good…and the different between the first and second run are pretty obvious…for the record…the generated file contains 105874 records…
Now…let’s see the Julia version of the code…
Actors_Info.jl
using DataFrames
start = time()
isdefined(:Actors) || (Actors = readtable("Actors_Table.csv", header=true, nastrings=["","NA"]))
drop_duplicates!(Actors)
complete_cases!(Actors)
Actor_Info = DataFrame(Actor_Id=Actors["Actor_Id"],Name=Actors["Name"],Gender=Actors["Gender"])
sortby!(Actor_Info, [:Gender])
writetable("Actor_Info_Julia.csv", Actor_Info)
finish = time()
println("Time: ", finish-start)


Here…we’re doing the same…we load the DataFrames package (But exclude that from the execution time), check if the file is loaded so we don’t load it again on the second run…eliminate duplicates, delete all null or NA, create a new DataFrame, sort it by “Gender” and finally write a new CVS file…

Well…the difference between the second and first run is very significative…but of course…way slower than R…
But…let me tell you one simple thing…Julia is still a brand new language…the DataFrames package is not part of the core Julia language, which means…that its even newer…and optimizations are being performed as we speak…I would say that for a young language…18 seconds to process 590,209 records is pretty awesome…and of course…my R experience surpasses greatly my Julia experience…

So…I don’t really want to leave you with the impression that Julia is not good or not fast enough…because believe me…it is…and you going to love my next experiment -;)

Let’s take a look at the R source code first…

Random_Names.R
start.time <- Sys.time()
names<-c("Anne","Gigi","Blag","Juergen","Marek","Ingo","Lars","Julia",
"Danielle","Rocky","Julien","Uwe","Myles","Mike", "Steven")

last_names<-c("Hardy","Read","Tejada","Schmerder","Kowalkiewicz","Sauerzapf",
"Karg","Satsuta","Keene","Ongkowidjojo","Vayssiere","Kylau",
"Fenlon","Flynn","Taylor")
full_names<-c()
for(i in 1:100000){
name<-sample(1:15, 1)
last_name<-sample(1:15, 1)
full_name<-paste(names[name],last_names[last_name],sep=" ")
full_names<-append(full_names,full_name)
}
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken

So this code is fairly simple…we have a couple of vectors with names and last names…then we loop 100000 times and then generate a couple of random numbers simply to read the vectors, create a full name and populate a new vector… with some random funny name combinations…

Well….the different between both runs is not really good…second time was a little bit higher…and 1 minute is kind of a lot…let’s see how Julia behaves…

Here’s the Julia source code…

Random_Numbers.jl
start = time()
names=["Anne","Gigi","Blag","Juergen","Marek","Ingo","Lars","Julia",
"Danielle","Rocky","Julien","Uwe","Myles","Mike", "Steven"]
last_names=["Hardy","Read","Tejada","Schmerder","Kowalkiewicz","Sauerzapf",
"Karg","Satsuta","Keene","Ongkowidjojo","Vayssiere","Kylau","Fenlon","Flynn","Taylor"]
full_names=String[]
full_name = ""
for i = 1:100000
name=rand(1:15)
last_name=rand(1:15)
full_name = names[name] * " " * last_names[last_name]
push!(full_names,full_name)
end
finish = time()
println("Time: ", finish-start)

So this code as well, creates two arrays with names and last names, do a loop 100000 times, generate a couple of random numbers, mix a name with a last name and then populate a new array with some mixed full names…

Just like in the R code…the second time took Julia a little bit more…but…less than a second?! That’s something like…amazingly fast and really took R by storm…
Now…I believe you will start to take Julia more seriously -:D
Hope you liked this blog…
Greetings,
Blag.
Development Culture.