并行计算—多线程(实验功能)—原子操作,关于样例的问题


#1

原文中 old_is 的输出应该时错了,实际输出大概如下图所示

julia


#2

不过一个疑问是, julia 的下标是从 1 开始的,那么这里 old_is 为啥不是 [1.0,3.0,6.0,10.0] 呢?
julia2


#3

文档确实有问题,你的结果应该是对的。

你执行 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


#4

感谢大佬!我确实是忘开多线程了。。。每个线程的任务分配 是在 for id in 1:4 确定,还是在有了 Theards.atomicadd!()时才确定呢(意思是如果没有atomic,是否电脑就根本不会尝试去开新线程)?这个我再看会资料。

问号加函数的查询方法学到了,感谢!


#5

你的循环开始的时候就会spawn线程,不管你有没有做计算
如楼上所说,你最好先检查一下到底启动了几个线程

julia> ENV["JULIA_NUM_THREADS"]
"4"

julia> Threads.@threads for i=1:4
           println(Threads.threadid())
       end
1
2
3
4

#6

这个“任务分配”具体指什么?

for id in 1:4 时只是给每个线程分了个 id 值。

atomicadd! 是指加法操作是原子的,一次只能有一个线程做这个操作。

没有 atomic 手动加锁也可以,这个和开不开线程应该没关系。锁都不加,可能会出错,或者结果很奇怪。


#7

明白了,任务分配指给线程分 id,因为想着如果循环是1:5,实际也只能有四个线程能用,这个分配的时间当时还没看到资料。感谢大佬:joy:


#8

感谢大佬,原样例中的old_is不确定,然后ids能按顺序的,这个确实很有趣:joy: