原文中 old_is 的输出应该时错了,实际输出大概如下图所示
不过一个疑问是, julia 的下标是从 1 开始的,那么这里 old_is 为啥不是 [1.0,3.0,6.0,10.0] 呢?
文档确实有问题,你的结果应该是对的。
你执行 Threads.nthreads()
看看输出是多少?
输出是 1 就代表你的环境变量没设置好,开不了多线程。
输出大于一,开启了多线程之后,old_is
的结果是不定的。
因为你不能确定哪个线程先拿到 i
。
多次执行结果多种多样。
julia> i = Threads.Atomic{Int}(0);
julia> ids = zeros(4);
julia> old_is = zeros(4);
julia> Threads.@threads for id in 1:4
@show i id
old_is[id] = Threads.atomic_add!(i, id)
ids[id] = id
end
i = Base.Threads.Atomic{Int64}(0)
i = Base.Threads.Atomic{Int64}(0)
i = Base.Threads.Atomic{Int64}(0)
i = Base.Threads.Atomic{Int64}(0)
id = 4
id = 3
id = 2
id = 1
julia> old_is
4-element Array{Float64,1}:
9.0
7.0
4.0
0.0
julia> ids
4-element Array{Float64,1}:
1.0
2.0
3.0
4.0
看 Threads.atomic_add!
的帮助
help?> Threads.atomic_add!
Threads.atomic_add!(x::Atomic{T}, val::T) where T <: ArithmeticTypes
Atomically add val to x
Performs x[] += val atomically. Returns the **old** value. Not defined for Atomic{Bool}.
For further details, see LLVM's atomicrmw add instruction.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_add!(x, 2)
3
julia> x[]
5
这个函数返回的不是相加的结果,而是相加之前的 x
的值,所以是从 0 开始,然后是 1,3,6
感谢大佬!我确实是忘开多线程了。。。每个线程的任务分配 是在 for id in 1:4 确定,还是在有了 Theards.atomicadd!()时才确定呢(意思是如果没有atomic,是否电脑就根本不会尝试去开新线程)?这个我再看会资料。
问号加函数的查询方法学到了,感谢!
你的循环开始的时候就会spawn线程,不管你有没有做计算
如楼上所说,你最好先检查一下到底启动了几个线程
julia> ENV["JULIA_NUM_THREADS"]
"4"
julia> Threads.@threads for i=1:4
println(Threads.threadid())
end
1
2
3
4
这个“任务分配”具体指什么?
for id in 1:4
时只是给每个线程分了个 id 值。
atomicadd!
是指加法操作是原子的,一次只能有一个线程做这个操作。
没有 atomic 手动加锁也可以,这个和开不开线程应该没关系。锁都不加,可能会出错,或者结果很奇怪。
明白了,任务分配指给线程分 id,因为想着如果循环是1:5,实际也只能有四个线程能用,这个分配的时间当时还没看到资料。感谢大佬
感谢大佬,原样例中的old_is不确定,然后ids能按顺序的,这个确实很有趣