使用MD模拟,我需要对粒子位置强制执行周期性边界条件。最简单的方法是使用mod(particle position, box dimension)
。由于我在3D空间工作,我制作了一个3D矢量类型:
immutable Vec3
x::Float32
y::Float32
z::Float32
end
一个mod函数:
f1(a::Vec3, b::Vec3) = Vec3(mod(a.x, b.x), mod(a.y, b.y), mod(a.z, b.z))
然而,当使用它时,它失败了:
julia> a = Vec3(11,-2,5)
Vec3(11.0f0,-2.0f0,5.0f0)
julia> b = Vec3(10,10,10)
Vec3(10.0f0,10.0f0,10.0f0)
julia> f1(a,b)
Vec3(5.0f0,10.0f0,NaN32)
如果我只是返回一个元组,它可以正常工作:
f2(a::Vec3, b::Vec3) = mod(a.x,b.x), mod(a.y,b.y), mod(a.z,b.z)
julia> f2(a,b)
(1.0f0,8.0f0,5.0f0)
作为测试,看它是否不喜欢类型构造函数中的mod,我尝试了一个更详细的方法:
function f3(a::Vec3, b::Vec3)
x = mod(a.x,b.x)
y = mod(a.y,b.y)
z = mod(a.z,b.z)
return Vec3(x,y,z)
end
julia> f3(a,b)
Vec3(5.0f0,10.0f0,NaN32)
然后,打印中间体的版本:
function f4(a::Vec3, b::Vec3)
x = mod(a.x,b.x)
y = mod(a.y,b.y)
z = mod(a.z,b.z)
println(x, " ", y, " ", z)
return Vec3(x,y,z)
end
julia> f4(a,b)
1.0 8.0 5.0
Vec3(1.0f0,8.0f0,5.0f0)
由于某种原因现在有效。我现在在多台计算机上尝试过这种方法,每种方法都有相同的结果。如果有人能够对此有所了解,我将非常感激。 Julia版本是:Version 0.3.2 (2014-10-21 20:18 UTC)
答案 0 :(得分:4)
我认为这可能是一个错误,甚至可能是一个LLVM错误。我能够在版本0.3.0上重现您的错误,但不能在0.4版本上重现。和你一样,我也通过在中间插入一个print语句来获得正确的结果。
此外,我发现两者都更简单
f1(a::Vec3, b::Vec3) = Vec3(mod(a.x,b.x),mod(a.y,b.y),1)
julia> f1(a,b)
Vec3(1.0f0,8.0f0,1.0f0)
AND 更复杂的
julia> f1(a::Vec3, b::Vec3) = Vec3(mod(a.x,b.x),mod(a.y,b.y),mod(a.z,b.z) + 1)
f1 (generic function with 1 method)
julia> f1(a,b)
Vec3(1.0f0,8.0f0,6.0f0)
两者都有效,但下一个不是
julia> f1(a::Vec3, b::Vec3) = Vec3(mod(a.x,b.x),mod(a.y,b.y),mod(a.z,b.z))
f1 (generic function with 1 method)
julia> f1(a,b)
Vec3(5.0f0,10.0f0,NaN32)
LLVM源也看起来正确。使用( fadd , frem , fadd )然后将结果存储在结果中。
julia> code_llvm(f1,(Vec3,Vec3))
define %Vec3 @"julia_f1;20242"(%Vec3, %Vec3) {
top:
%2 = extractvalue %Vec3 %1, 0, !dbg !1733
%3 = extractvalue %Vec3 %1, 1, !dbg !1733
%4 = extractvalue %Vec3 %1, 2, !dbg !1733
%5 = extractvalue %Vec3 %0, 0, !dbg !1733
%6 = frem float %5, %2, !dbg !1733
%7 = fadd float %2, %6, !dbg !1733
%8 = frem float %7, %2, !dbg !1733
%9 = insertvalue %Vec3 undef, float %8, 0, !dbg !1733
%10 = extractvalue %Vec3 %0, 1, !dbg !1733
%11 = frem float %10, %3, !dbg !1733
%12 = fadd float %3, %11, !dbg !1733
%13 = frem float %12, %3, !dbg !1733
%14 = insertvalue %Vec3 %9, float %13, 1, !dbg !1733
%15 = extractvalue %Vec3 %0, 2, !dbg !1733
%16 = frem float %15, %4, !dbg !1733
%17 = fadd float %4, %16, !dbg !1733
%18 = frem float %17, %4, !dbg !1733
%19 = insertvalue %Vec3 %14, float %18, 2, !dbg !1733, !julia_type !1734
ret %Vec3 %19, !dbg !1733
但原生指令看起来不正确, XMM2 移至 XMM0 ,稍后 XMM0 用作 addss的操作数,但 XMM2 似乎未初始化。
julia> code_native(f1,(Vec3,Vec3))
.section __TEXT,__text,regular,pure_instructions
Filename: none
Source line: 1
push RBP
mov RBP, RSP
sub RSP, 16
movss DWORD PTR [RBP - 4], XMM5
Source line: 1
movaps XMM0, XMM2
movaps XMM1, XMM5
movabs RAX, 140735600044048
call RAX
movss XMM1, DWORD PTR [RBP - 4]
addss XMM0, XMM1
movabs RAX, 140735600044048
add RSP, 16
pop RBP
jmp RAX
提交this issue以查找可能的LLVM错误。