奇怪的建筑行为

时间:2014-11-07 05:14:01

标签: julia

使用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)

1 个答案:

答案 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

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错误。