我有以下简单代码:
function hamming4(bits1::Integer, bits2::Integer)
return count_ones(bits1 ⊻ bits2)
end
function random_strings2(n, N)
mask = UInt128(1) << n - 1
return [rand(UInt128) & mask for i in 1:N]
end
function find_min(strings, n, N)
minsofar = fill(n, Threads.nthreads())
# minsofar = n
Threads.@threads for i in 1:N
# for i in 1:N
for j in i+1:N
dist = hamming4(strings[i], strings[j])
if dist < minsofar[Threads.threadid()]
minsofar[Threads.threadid()] = dist
end
end
end
return minimum(minsofar)
#return minsofar
end
function ave_min(n, N)
ITER = 10
strings = random_strings2(n, N)
new_min = find_min(strings, n, N)
avesofar = new_min
# print("New min ", new_min, ". New ave ", avesofar, "\n")
total = avesofar
for i in 1:ITER-1
strings = random_strings2(n, N)
new_min = find_min(strings, n, N)
avesofar = avesofar*(i/(i+1)) + new_min/(i+1)
print("Iteration ", i, ". New min ", new_min, ". New ave ", round(avesofar; digits=2), "\n")
end
return avesofar
end
N = 2^16
n = 99
print("Overall average ", ave_min(n, N), "\n")
当我在Linux上的AMD 8350上运行时,CPU使用率约为430%(而不是接近800%)。
是否可以使并行化工作更有效率?
我还注意到了一个名为LoopVectorization.jl的外观非常新的软件包。当我以一种可向量化的方式计算the Hamming distance时,是否也可以以此方式加快代码的速度?
可以使用LoopVectorization.jl对代码进行矢量化吗?
(我对Julia完全陌生)
答案 0 :(得分:4)
代码的并行化似乎是正确的。
您很有可能在Atom或其他IDE中运行它。默认情况下,Atom仅使用一半的核心(更确切地说,仅使用物理而非逻辑核心)。
例如在我的计算机上的Atom中运行:
julia> Threads.nthreads()
4
您需要做的是显式设置JULIA_NUM_THREADS
Windows命令行(仍假设8个逻辑内核)
set JULIA_NUM_THREADS=8
Linux命令行
export JULIA_NUM_THREADS=8
这样做之后,您的代码将占据我所有内核的100%。
讨论之后-通过使用Distributed
而不是Threads
,您可以将时间减少到单线程时间的20%左右,因为这样可以避免内存共享:
代码大致如下所示:
using Distributed
addprocs(8)
@everywhere function hamming4(bits1::Integer, bits2::Integer)
return count_ones(bits1 ⊻ bits2)
end
function random_strings2(n, N)
mask = UInt128(1) << n - 1
return [rand(UInt128) & mask for i in 1:N]
end
function find_min(strings, n, N)
return @distributed (min) for i in 1:N-1
minimum(hamming4(strings[i], strings[j]) for j in i+1:N)
end
end
### ... the rest of code remains unchanged