同一段代码用cuda和vulkan运行结果不一样

import taichi as ti

ti.init(arch=ti.cuda) # 换成vulkan就会出问题

quality = 2 
n_rigid_p = 80*quality # 每条边 /4个点
rigid_line = ti.Vector.field(2,ti.f32,shape=n_rigid_p)
rigid_p = ti.Vector.field(2,dtype=ti.f32,shape=n_rigid_p) # 每个点对应的位置
center = ti.Vector.field(2,dtype=ti.f32,shape=1)
my_test = ti.Vector.field(2,dtype=ti.f32,shape=1) # 用于输出结果

@ti.func
def init_rigid(x:ti.f32,y:ti.f32,w:ti.f32):
    k = (n_rigid_p / 4)
    dw = w/k
    for i in range(k):
        rigid_line[i] = ti.Vector([x+i*dw,y])
    for i in range(k,2*k):
        rigid_line[i] = ti.Vector([x+w,y+(i-k)*dw])
    for i in range(2*k,3*k):
        rigid_line[i] = ti.Vector([x+w-(i-2*k)*dw,y+w])
    for i in range(3*k,4*k):
        rigid_line[i] = ti.Vector([x,y+w-(i-3*k)*dw])
    for i in range(n_rigid_p):
        rigid_p[i] = (rigid_line[i]+rigid_line[(i+1)%n_rigid_p])/2
        center[0]+=rigid_p[i]
    center[0] /= n_rigid_p

@ti.func
def compute_rigid():
    center[0] = ti.Vector([0.0,0.0])
    for i in rigid_p:
        center[0]+=rigid_p[i]
    center[0] = center[0] / n_rigid_p
    my_test[0] = ti.Vector([0,0])
    for i in range(n_rigid_p):
        x_rel = ti.Vector([0.0,0.0])
        x_rel += (rigid_p[i] - center[0])
        my_test[0] += x_rel

@ti.kernel
def init():
    init_rigid(0.25,0.65,0.0625)

@ti.kernel
def sub_step():
    compute_rigid()

def show(canvas):
    canvas.circles(rigid_p, radius=0.003, color=(0, 0.98, 0.97))

def main():
    init()
    window = ti.ui.Window("my mpm", res=(512, 512), vsync=True)
    canvas = window.get_canvas()
    canvas.set_background_color((0.067, 0.184, 0.255))
    step_size = 2
    while window.running:
        for i in range(step_size):
            sub_step()
        print(my_test[0])
        show(canvas)
        window.show()


if __name__ == '__main__':
    main()

这段代码用cuda运行起来是正常的,但是用vulkan就很奇怪,我不知道这段代码是哪里出问题了,还是说我环境有问题,但我运行其他example里的程序好像都是正常的。
cuda的结果


vulkan的结果

初步检查了一下你的代码,误差的原因似乎在下面这个部分

这里是不是可以改写成这样就没问题了?

    for i in range(n_rigid_p):
        my_test[0] += (rigid_p[i] - center[0])

我试了一下还是不行,而且就算这样可以感觉也不太对劲。

可以具体说一下是哪里不对吗,预期结果和实际结果各是如何的,以及一份尽量简洁的复现代码,这样比较方便我们排查问题~

import taichi as ti

ti.init(arch=ti.cuda) # 换成vulkan就会出问题

n_rigid_p = 160 # 每条边 /4个点
rigid_p = ti.Vector.field(2,ti.f32,shape=n_rigid_p) # 点的位置,它是均匀分布在一个正方形的边上的
center = ti.Vector.field(2,dtype=ti.f32,shape=1) # 正方形的中心
my_test = ti.Vector.field(2,dtype=ti.f32,shape=1) # 用于输出结果

@ti.kernel
def init_rigid(x:ti.f32,y:ti.f32,w:ti.f32):
    # x,y就是正方形的左下角,w是正方形的边长
    k = (n_rigid_p / 4) #每一条边上的点的个数
    dw = w/k
    # 初始化每一个点的位置
    for i in range(k):
        rigid_p[i] = ti.Vector([x+i*dw,y])
    for i in range(k,2*k):
        rigid_p[i] = ti.Vector([x+w,y+(i-k)*dw])
    for i in range(2*k,3*k):
        rigid_p[i] = ti.Vector([x+w-(i-2*k)*dw,y+w])
    for i in range(3*k,4*k):
        rigid_p[i] = ti.Vector([x,y+w-(i-3*k)*dw])


@ti.kernel
def test():
    #先求出中心
    center[0] = ti.Vector([0.0,0.0])
    for i in rigid_p:
        center[0]+=rigid_p[i]
    center[0] = center[0] / n_rigid_p
    
    # 这里就是出问题的代码,它应该是一个很接近[0,0]的向量
    # 但是使用ti.init(arch=ti.vulkan) 结果却很奇怪
    # 使用ti.init(arch=ti.cuda)感觉更符合预期结果
    my_test[0] = ti.Vector([0,0])
    for i in rigid_p:
        my_test[0] += (rigid_p[i] - center[0])


def main():
    init_rigid(0.25,0.65,0.0625)
    test()
    print(my_test[0])


if __name__ == '__main__':
    main()

非常感谢,我把无关的代码都去掉了,只要把arch=cuda换成vulkan就可以复现了(如果问题不是出在我的环境上)

感谢提供测试代码!如果你代码中的 centermy_test 都只包含一个 ti.Vector 的话,声明可以改成:

center = ti.Vector.field(2,dtype=ti.f32,shape=())
my_test = ti.Vector.field(2,dtype=ti.f32,shape=())

在赋值时则使用 center[None] = ...my_test[None] 而不是 center[0]my_test[0],这样 Vulkan 上也会得出一个接近于 0 的结果,你可以测试一下。
至于为什么不能像你现在这样把 center 定义成 shape=1 这的确有可能是个 bug,可以请你去 repo 发个 bug report 吗(https://github.com/taichi-dev/taichi/issues)
感谢:pray:

在 Taichi 主仓整理了一个 issue report 这个现象:[bug] Inconsistent results on Vulkan backend · Issue #7923 · taichi-dev/taichi · GitHub
Report 里的复现代码进行了进一步精简,目前问题似乎的确是 Vulkan backend 有bug的样子