同一个程序用ti.cpu与ti.cuda计算结果不同

一个统计点径向分布的代码。
程序在ti.cpu与ti.cuda上都没有报错,但是输出来的结果不同,有点好奇是怎么回事。

import taichi as ti
from numpy import *
from os import listdir

dr=0.5
maxr=100;

@ti.data_oriented
class Staticgr:
    def __init__(self, N ,M,CX,CY) -> None:
        self.n = N
        self.m = M
        self.cx = CX
        self.cy = CY        
        self.pos = ti.Vector.field(2, ti.f64, shape=self.n)
        self.grRe = ti.Vector.field(1, ti.f64, shape=self.m)
        
    def initialize(self): 
        for i in range(self.n):
            self.pos[i] = ti.Vector([self.cx[i], self.cy[i]])
        for j in range(self.m):
            self.grRe[j]=ti.Vector([0])  
             
    @ti.kernel
    def computegr(self):
        for i in range(self.n):
            p = self.pos[i]
            for j in range(self.n):
                if i != j:
                    diff = self.pos[j] - p
                    r=ti.sqrt(diff[0]*diff[0]+diff[1]*diff[1])
                    if r<maxr:
                        ids=ti.ceil(r/dr)-1
                        self.grRe[ids] +=1.0
                        
def file2matrix(filename):
    fr=open(filename)
    numberOfLines=len(fr.readlines())
    returnMat=zeros((numberOfLines,2))
    fr=open(filename)
    index=0
    for line in fr.readlines():
        line=line.strip()
        listFromLine=line.split('\t')
        returnMat[index,:]=listFromLine[0:2]
        index+=1
    return returnMat

ti.init(kernel_profiler=True, arch=ti.cuda)
data=file2matrix("7.txt")
gg = Staticgr(N=data.shape[0], M=ti.ceil(maxr/dr),CX=data[:,0],CY=data[:,1])
gg.initialize()
gg.computegr()
ti.profiler.print_kernel_profiler_info()
print(gg.grRe[98])

cpu下输出的结果是 270710,gpu下输出的结果则是270712
是因为计算精度的问题吗?有什么办法可以调试的?

我觉得是你的 compute 函数不是 determine function。因为 for i in range(self.n)是并行执行的,不同的循环里在第二层循环都用到了self.pos,不同线程得到的 self.pos[j] 可能不是一样的结果。

谢谢啦!是因为 self.pos[j]的赋值或者从主机拷贝给设备的时候出问题了嘛?有什么解决的思路嘛?

其实是不同线程不确定顺序的 read/write self.pos 导致的结果出现问题。你可以通过存储中间的一个field 来read, 另外一个field来atomic的write结果就可以了。

请问怎么设置可以按照顺序执行?

你可以通过设置最大线程数为1来达到顺序执行的目的:

ti.init(arch=ti.cpu, cpu_max_num_threads=1)
1 个赞

非常感谢