我试图在Threads.@threads for
循环中做一些线性代数,它会返回一些奇怪的结果。似乎矩阵在循环中没有正确地相乘。在线程for循环中安全吗?
以下是生成TxR
矩阵NxN
表的最小工作示例。对于R
次迭代中的每一次,第(t + 1)个矩阵是具有另一个随机矩阵的(t)-th的乘积。乘法由不同的线程执行,然后由一个线程检查正确性。该函数应返回零的矩阵。对N<=3
执行此操作时,N>=4
的结果中有一些。
function testMM(T, R, N)
m1 = zeros(Int64, (T,R,N,N))
m2 = rand(0:2, (T-1,R,N,N))
m1[1,:,:,:] = rand(0:1,(R,N,N))
Threads.@threads for i=1:R
for t=2:T
m1[t,i,:,:] = m2[t-1,i,:,:] * m1[t-1,i,:,:]
end
end
odds = zeros(Int64,(T-1,R))
for i=1:R
for t=2:T
if m1[t,i,:,:] != m2[t-1,i,:,:] * m1[t-1,i,:,:]
odds[t-1,i] = 1
end
end
end
return odds
end
Threads.nthreads()
对我来说是4。在Windows上测试稳定的64位Julia 0.5.2,0.5.3,0.6.0。
编辑:这个例子更简单:矩阵的几个副本独立地平方几次。对于所有副本,结果应该相同,但函数通常对N>=4
返回false。看起来好像不同线程的数据在BLAS内某处混合。
function testMM2(T, R, N)
m0 = rand(0:2, (N,N))
m = [deepcopy(m0) for i=1:R]
Threads.@threads for i=1:R
for t=1:T
m[i] = m[i]^2
end
end
return all(x->(x==m[1]),m)
end