julia本身是一门很快速的语言,但是现代计算机往往具有多核心多线程设计,因此,充分发挥硬件,能进一步提高效率

多线程的启动

julia从1.5开始新添加了命令行参数-t num_procs,例如,你想启动一个10个线程的julia,那么就可以执行:

  1. julia -t 10

进入REPL后,可以查看当前线程数:

  1. Threads.nthreads()
  2. 10

如何多线程?

julia提供了一个简单的宏函数,来快速的包装for循环,使其可以将任务拆分为n份,每分独立执行

Threads.@threads

例如:

a = zeros(10)

Threads.@threads for i = 1:10
    a[i] = Threads.threadid()
end

非常简单的,可以快速将你的单线程函数转化为多线程。

线程安全

举个例子:

acc = Ref(0)

@threads for i in 1:1000
    acc[] += 1
end

正常情况下,该流程计算的是从累加1000个1,结果应该是1000才对,但是因为多线程调度,导致acc最终的结果并非为1000,即得到了错误的计算结果。

第一个解决办法是使用原子操作

acc = Atomic{Int64}(0)

@threads for i in 1:1000
    atomic_add!(acc, 1)
end

另一种方法是在变量上添加线程锁,使其同一时间有且只有一个线程可以操作该变量

acc = Ref(0)
l = ReentrantLock()

@threads for i=1:1000
    lock(l) do 
        acc[]+=1
    end
end

当然,举例只是为了说明多线程的安全问题,该变量的累积添加了线程锁后其实和单线程操作没有任何区别,反而因为线程调度影响了性能。因此,需要综合考虑你的项目是否需要多线程。