优化技巧 #

一、避免全局变量 #

1.1 问题 #

julia
global_var = 10

function use_global()
    total = 0
    for i in 1:10^6
        total += global_var
    end
    return total
end

@time use_global()

1.2 解决方案 #

julia
function use_local(var)
    total = 0
    for i in 1:10^6
        total += var
    end
    return total
end

@time use_local(10)

1.3 使用常量 #

julia
const CONST_VAR = 10

function use_const()
    total = 0
    for i in 1:10^6
        total += CONST_VAR
    end
    return total
end

@time use_const()

二、预分配 #

2.1 问题 #

julia
function grow_array(n)
    arr = Int[]
    for i in 1:n
        push!(arr, i)
    end
    return arr
end

@time grow_array(10^6)

2.2 解决方案 #

julia
function preallocate(n)
    arr = Vector{Int}(undef, n)
    for i in 1:n
        arr[i] = i
    end
    return arr
end

@time preallocate(10^6)

2.3 使用sizehint! #

julia
function with_sizehint(n)
    arr = Int[]
    sizehint!(arr, n)
    for i in 1:n
        push!(arr, i)
    end
    return arr
end

三、类型稳定性 #

3.1 问题 #

julia
function unstable(x)
    if x > 0
        return x
    else
        return 0.0
    end
end

@code_warntype unstable(1)

3.2 解决方案 #

julia
function stable(x::T) where {T<:Real}
    if x > 0
        return T(x)
    else
        return zero(T)
    end
end

@code_warntype stable(1)

四、循环优化 #

4.1 避免边界检查 #

julia
function with_bounds_check(arr)
    total = 0.0
    for i in 1:length(arr)
        total += arr[i]
    end
    return total
end

function without_bounds_check(arr)
    total = 0.0
    @inbounds for i in 1:length(arr)
        total += arr[i]
    end
    return total
end

arr = rand(10^6)
@time with_bounds_check(arr)
@time without_bounds_check(arr)

4.2 使用@simd #

julia
function regular_sum(arr)
    total = 0.0
    for x in arr
        total += x
    end
    return total
end

function simd_sum(arr)
    total = 0.0
    @simd for x in arr
        total += x
    end
    return total
end

arr = rand(10^6)
@time regular_sum(arr)
@time simd_sum(arr)

4.3 列优先访问 #

julia
function row_major(mat)
    total = 0.0
    for i in 1:size(mat, 1)
        for j in 1:size(mat, 2)
            total += mat[i, j]
        end
    end
    return total
end

function col_major(mat)
    total = 0.0
    for j in 1:size(mat, 2)
        for i in 1:size(mat, 1)
            total += mat[i, j]
        end
    end
    return total
end

mat = rand(1000, 1000)
@time row_major(mat)
@time col_major(mat)

五、避免分配 #

5.1 使用广播 #

julia
function with_allocation(arr)
    arr .+ 1
end

function without_allocation!(arr)
    arr .+= 1
end

arr = rand(10^6)
@time with_allocation(arr)
@time without_allocation!(arr)

5.2 使用预分配结果 #

julia
function compute!(result, a, b)
    result .= a .+ b
end

a = rand(10^6)
b = rand(10^6)
result = similar(a)

@time compute!(result, a, b)

六、实践练习 #

6.1 练习1:优化求和 #

julia
function slow_sum(arr)
    total = 0
    for x in arr
        total += x
    end
    return total
end

function fast_sum(arr)
    total = zero(eltype(arr))
    @inbounds @simd for x in arr
        total += x
    end
    return total
end

arr = rand(10^6)
@time slow_sum(arr)
@time fast_sum(arr)

6.2 练习2:优化矩阵乘法 #

julia
function slow_matmul(A, B)
    C = zeros(size(A, 1), size(B, 2))
    for i in 1:size(A, 1)
        for j in 1:size(B, 2)
            for k in 1:size(A, 2)
                C[i, j] += A[i, k] * B[k, j]
            end
        end
    end
    return C
end

function fast_matmul(A, B)
    C = zeros(size(A, 1), size(B, 2))
    @inbounds for i in 1:size(A, 1)
        for k in 1:size(A, 2)
            for j in 1:size(B, 2)
                C[i, j] += A[i, k] * B[k, j]
            end
        end
    end
    return C
end

A = rand(100, 100)
B = rand(100, 100)
@time slow_matmul(A, B)
@time fast_matmul(A, B)

6.3 练习3:优化字符串处理 #

julia
function slow_concat(n)
    s = ""
    for i in 1:n
        s *= string(i)
    end
    return s
end

function fast_concat(n)
    parts = String[]
    for i in 1:n
        push!(parts, string(i))
    end
    return join(parts)
end

@time slow_concat(1000)
@time fast_concat(1000)

七、总结 #

本章我们学习了:

  1. 避免全局变量:使用局部变量和常量
  2. 预分配:避免动态增长
  3. 类型稳定性:保持类型一致
  4. 循环优化:@inbounds、@simd、列优先
  5. 避免分配:广播和预分配结果

接下来让我们学习Julia的类型稳定性!

最后更新:2026-03-27