Benchmarking Solutions to Mrode (4th Ed.): BLUPF90, R, and Julia
The publication of the 4th edition of Linear Models for the Prediction of the Genetic Merit of Animals by R. A. Mrode and I. Pocrnic (2023, CABI) provides a comprehensive pedagogical reference for linear mixed models in quantitative genetics and animal breeding. Accompanying the text are three open-source companion solution repositories implementing the worked examples across the textbook:
- BLUPF90 Suite (
Examples_BLUPF90): Parameter and data setups for the legacy Fortran 90 binaries developed by Ignacy Misztal and colleagues at the University of Georgia. - R Scripts (
Examples_R): Educational scripts using standard R packages (Matrix,pedigreemm,lme4, and thetidyverse). - Julia Package (
Mrode4edExamples.jl/Examples-Julia): A native, type-stable implementation built on the domain-specific librariesRelationshipMatrices.jlandBreeding.jl.
Below is an empirical benchmark and architectural evaluation comparing the computational paradigms, execution performance, numerical reliability, and algorithmic scaling of these three solution suites.
Some interesting Julia codes
Julia is fast, composable, dynamic, general, reproducible and open source. The codes below were taken from https://julialang.org. I found it very illustrating.
Multiple dispatch
struct Dog end
struct Cat end
dog, cat = Dog(), Cat()
meet(a::Dog, b::Dog) = "The dogs play together"
meet(a::Dog, b::Cat) = "The dog chases the cat"
meet(a::Cat, b::Dog) = "The cat hisses at the dog"
meet(a::Cat, b::Cat) = "The cats ignore each other"
meet(dog, cat)
meet(dog, dog)
meet(cat, cat)Display customization
struct Nutshell{T}
contents::T
end
Base.show(io::IO, n::Nutshell) = print(io, "🥜 ", n.contents, " 🥜")
Nutshell("Julia")Unicode and math
α, β = .5, .3
f(x) = α * x + β
Σ(v) = reduce(+, v)
Σ(f.(1:5))Comprehensions
[x^2 for x in 1:5]Broadcasting
A = [1 2; 3 4]
sin.(A) .+ 1
Dict(c => i for (i, c) in enumerate("julia")Piping and composition
1:5 |> sum |> sqrt
(sqrt ∘ sum)(1:5) # equiv. above
map(exp ∘ abs, [-1, 2, -3])Destructuring
(a, b, c) = 1:3
a, c # => (1, 3)
head, tail... = ["first", "second", "third"]
head, tail # => ("first", ["second", "third"])Metaprogramming
ex = :(1 + 2 * 3)
typeof(ex) # => Expr
eval(ex) # => 7Easy package install
using DataFrames
# if not installed, prompted for installation, after 'y' answer
df = DataFrame(name = ["Alice", "Bob"], age = [25, 30])Defaults and keywords args
function greet(name, greeting = "Hello"; punctuation = "!")
"$greeting, $name$puctuation"
end
greet("Julia") # "Hello, Julia!"
greet("world", "Hi"; puctuation = ".") # "Hi, world."Multi-threading
function fib(n)
n < 2 && return n
t = Threads.@spawn fib(n-2)
return fib(n-1) + fetch(t)
end
fib(10)
Threads.nthreads() # => threads assigned to JuliaBuild-in REPL modes
# Default Julia mode, backspace from other modes
# Press ] for package mode
# Press ; for shell mode
# Press ? for helps
# Press $ for R mode, if RCall.jl is installedCode introspection (simplified)
f(x, y) = x + y
@code_warntype f(1, 2)
@code_llvm f(1, 2)
@code_native f(1, 2)