Skip to content
Volume J · The TensorCore.si Library

Julia

Python's ease with C's speed, for science and ML.

Julia was designed for fast numerical and scientific computing. It looks like Python or MATLAB but compiles to fast native code, which is why it is used for climate models, pharmaceutical simulations and differentiable machine learning with Flux and Lux.

Prologue

Why learn Julia?

Julia solves the two-language problem: you can prototype and run production-speed numerical code in the same language.

  • Fast: JIT compilation gives near-C speed for loops.
  • Built for maths: arrays, linear algebra and Unicode maths symbols are first-class.
  • ML and GPUs: Flux, Lux and CUDA.jl run neural networks on NVIDIA GPUs.
Prologue

Set up and run your first program

Install Julia with juliaup from julialang.org, then use the REPL or VS Code.

terminal
julia --version
julia hello.jl
hello.jl
name = "Ada"
println("Hello, AI! Welcome to Julia, $name.")
TipPress ] in the REPL to enter package mode, then add Flux to install packages.
Chapter 1

Variables and numbers

No declarations needed. Julia has many numeric types (Int64, Float32, Float16, BigInt) and you can write 2x for 2 * x.

variables.jl
layers = 32
lr = 3e-4
params = 8_030_000_000
x = Float16(0.1)          # half precision, like on GPUs
println("FP16 size: ", params * 2 / 1e9, " GB")
println(typeof(x), " ", 2layers)
Chapter 2

Arrays and broadcasting

Arrays are 1-indexed and column-major. A dot (.) broadcasts any function over every element, with no loops.

arrays.jl
w = [0.5, -1.0, 2.0, 0.25]
println(w .* 2)            # element-wise
println(sum(w .^ 2))
A = rand(3, 3)
v = rand(3)
println(A * v)             # matrix-vector product
println(size(A), " ", w[1])  # first element is index 1
Chapter 3

Functions and multiple dispatch

Functions can have several methods chosen by the types of all arguments. This multiple dispatch is Julia's central idea.

functions.jl
params(layers, width=4096) = 12 * layers * width^2

describe(x::Integer) = "an integer"
describe(x::AbstractFloat) = "a float"
describe(x::String) = "text"

println(params(32))
println(describe(8), ", ", describe(8.0), ", ", describe("fp8"))
Chapter 4

Control flow and comprehensions

Loops and conditionals end with end. Comprehensions build arrays in one line.

control.jl
for epoch in 1:3
    println("epoch ", epoch)
end
bits = 8
name = bits == 16 ? "FP16" : bits == 8 ? "FP8" : "other"
squares = [i^2 for i in 1:5 if isodd(i)]
println(name, " ", squares)
Chapter 5

Structs and types

struct defines immutable types (mutable struct for mutable ones). Methods are defined outside the struct.

structs.jl
struct Gpu
    name::String
    vram_gb::Int
end
fits(g::Gpu, gb) = gb <= g.vram_gb
Base.show(io::IO, g::Gpu) = print(io, g.name, " (", g.vram_gb, " GB)")

g = Gpu("H100", 80)
println(g, " fits 70 GB: ", fits(g, 70))
Part II · AI with Julia

AI with Julia

Julia is used for scientific machine learning, where neural networks are combined with physics models, and for fast research code. Automatic differentiation works on ordinary Julia code, and CUDA.jl runs it on GPUs.

The essential libraries

Flux.jlSimple, flexible deep learning.
Lux.jlExplicit-parameter neural networks for SciML.
CUDA.jlWrite and run GPU kernels in Julia.
MLJ.jlA unified interface to classic ML models.

Gradient descent from scratch

Thanks to broadcasting, the gradient is one line per parameter.

gradient.jl
x = range(-1, 1, length=100)
y = 3 .* x .+ 0.5 .+ 0.1 .* randn(100)
w, b, lr = 0.0, 0.0, 0.1
for step in 1:500
    err = (w .* x .+ b) .- y
    global w -= lr * sum(2 .* err .* x) / length(x)
    global b -= lr * sum(2 .* err) / length(x)
end
println("w = ", round(w, digits=2), ", b = ", round(b, digits=2))
Part III · Build an AI agent

Build an AI agent in Julia

HTTP.jl and JSON3.jl handle requests and messages. The loop sends tools to a local model and runs any tool it calls.

Your goal→Model plans→Tool call→Your code runs the tool→Result back to model→Final answer
agent.jl
using HTTP, JSON3     # ] add HTTP JSON3

get_weather(city) = "It is 24°C and sunny in $city."
tools = [Dict("type" => "function", "function" => Dict("name" => "get_weather",
    "description" => "Weather for a city",
    "parameters" => Dict("type" => "object", "properties" => Dict("city" => Dict("type" => "string")),
                         "required" => ["city"])))]
messages = Any[Dict("role" => "user", "content" => "Should I take an umbrella in Lahore today?")]

for round in 1:5
    res = HTTP.post("http://localhost:11434/v1/chat/completions", ["Content-Type" => "application/json"],
                    JSON3.write(Dict("model" => "llama3.1", "messages" => messages, "tools" => tools)))
    msg = JSON3.read(res.body).choices[1].message
    push!(messages, msg)
    calls = get(msg, :tool_calls, [])
    if isempty(calls)
        println(msg.content); break
    end
    for call in calls
        args = JSON3.read(call.function.arguments)
        push!(messages, Dict("role" => "tool", "tool_call_id" => call.id, "content" => get_weather(args.city)))
    end
end

PromptingTools.jl offers a higher-level API with tool calling across providers.

Run it locallyInstall Ollama, run ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.
Part IV · Your path

Julia learning roadmap

Tick items off as you go. Your progress is saved in this browser.

Beginner

Intermediate

Advanced

Part IV · Your path

Projects to build

SimulationModel a falling object with DifferentialEquations.jl.
Neural net from scratchTrain an MNIST classifier with Flux.
GPU kernelWrite a vector-add kernel with CUDA.jl.
Reference

Julia cheat sheet

TaskSyntax
Printprintln("x = $x")
Arrayv = [1, 2, 3]
Broadcastv .* 2
Functionf(x) = x^2
Structstruct P; x::Int; end
Comprehension[i^2 for i in 1:5]
Reference

Common mistakes

  • Arrays start at index 1.
  • The first call of a function is slow because it compiles; time the second call.
  • Changing a variable's type inside a loop (type instability) slows code down.
Reference

Where to go next

On TensorCore.si: Python volume, MATLAB volume.

Keyboard: [ previous language · ] next language · / search the library