想知道为什么这个代码无法并行呢(?

大概就是一个RK4,可以运行,但是CPU占用只有10%几qwq,萌新的第一个程序,不知道哪里有问题

import taichi

m=20
k=1
step=0.01
begin=0
end=70
xlong= 20

xlist1=[0,0.2,0.4,0.8,1.2,1.6,2.4,3.2,4,5.6,7.2,8.8,12,15.2,18.4,24.8,31.2,37.6,50.4,63.2]
ylist1=[
[0,0.44721,0.63246,0.89443,1.09545,1.26491,1.54919,1.78885,2,2.36643,2.68328,2.96648,3.4641,3.89872,4.28952,4.97996,5.5857,6.13188,7.0993,7.94984]
,[0.9742,0.74616,0.69505,0.60067,0.56271,0.52789,0.46539,0.43908,0.40448,0.36854,0.33803,0.32939,0.30931,0.30803,0.2712,0.27834,0.27448,0.27278,0.27213,0.24438]
,[0.02214,0.20704,0.23472,0.32203,0.33179,0.37326,0.4045,0.43486,0.48729,0.48547,0.52775,0.55154,0.57585,0.58932,0.60244,0.60759,0.60589,0.60845,0.60477,0.61639]
]

taichi.init(arch=taichi.cpu)
xlist=taichi.field(float,shape=(1,xlong))
ylist=taichi.field(float,shape=(3,xlong))
templist=taichi.field(float,(1,m))
y=taichi.field(float,shape=(5*m,m))
for i in range(m):
    for j in range(i):
        y[5*i,j]=1

for i in range(xlong):
    xlist[0,i]=xlist1[i]
    for j in range(3):
        ylist[j,i]=ylist1[j][i]

@taichi.func
def fieldmult(yindex,toindex):
    tempy0=temp=y[yindex,0]
    y[toindex,0]=k*y[yindex,m-1]+k*y[yindex,1]-2*k*y[yindex,0]
    for i in taichi.static(range(1,m-1)): #期望这里可以并行
        tempnext=y[yindex,i]
        y[toindex,i]=k*temp+k*y[yindex,i+1]-2*k*y[yindex,i]
        temp=tempnext
    y[toindex,m-1] = k * temp + k * tempy0 - 2 * k * y[yindex,m-1]
@taichi.func
def fieldadd(aindex1,aindex2,bindex,mult1,mult2):
    for i in taichi.static(range(m)): #期望这里可以并行
        y[bindex,i]=mult2*y[aindex2,i]+mult1*y[aindex1,i]
@taichi.func
def RK4_L2(x:float,x1:float,h:float,oe:taichi.int8)->float:
    t0 = 0
    L2SUM=taichi.Vector([0.0,0.0,0.0])
    ysum=taichi.Vector([0.0,0.0,0.0])
    while(taichi.abs(x-x1)>h*0.5):
        if (taichi.abs(x - xlist[0,t0]) < h * 0.5):
            ysum[0]=0.0
            for i in range(0,oe):
                ysum[0]+=y[5*oe,i]
            ysum[0] = ysum[0] / oe #fi/fc
            ysum[1] = (y[5*oe,m-1] + y[5*oe,oe]) / oe #fra
            ysum[2] = 1 - ysum[1] - ysum[0] #fa
            for i in taichi.static(range(3)):
                L2SUM[i] += (ysum[i] - ylist[i,t0]) ** 2
            t0 += 1
        # k1
        fieldmult(5*oe,5*oe+1)
        # k2
        fieldadd(5*oe,5*oe+1,5*oe+2,1,h*0.5)
        fieldmult(5*oe+2,5*oe+2)
        # k3
        fieldadd(5*oe,5*oe+2,5*oe+3,1,h*0.5)
        fieldmult(5*oe+3,5*oe+3)
        # k4
        fieldadd(5*oe,5*oe+3,5*oe+4,1,h*0.5)
        fieldmult(5 * oe + 4,5 * oe + 4)
        for i in taichi.static(range(m)):
            y[5*oe, i] += h/6.0*(y[5*oe+1, i] + 2 * y[5*oe+2, i]+y[5*oe+4, i] + 2 * y[5*oe+3, i])
        x += h
    return (L2SUM[0]+L2SUM[1]+L2SUM[2])**0.5
@taichi.kernel
def fitting()->int:
    for i in taichi.static(range(2,m-2)):
        templist[0,i]=RK4_L2(0.0,end,step,i) #首先是期望这里可以并行
    temp=2
    tempvalue=templist[0,2]
    for j in range(1):
        for i in taichi.static(range(3,m-2)):
            if(templist[0,i]<tempvalue):
                temp=i
                tempvalue=templist[0,i]
    print(tempvalue)
    return temp

print(fitting())

Hi, @misaka. 在 Taichi 的 kernel 中,只有顶层的 for loop 是并行的,处于非顶层的 for loop 则不会。由于定义在 @ti.func 中的代码会被内联到 kernel 中,所以定义在 ti.func 中的 for loop 如果内联到 kernel 中不是处于顶层的话,就不会被并行。你的代码中 fieldmul 在内联以后位于 while loop 下面,所以不是并行的。

感谢,但是可能连fitting内的RK4_L2都没有并行(速度比不用taichi还慢),这个是为什么呢? 或者,有没有提高性能的建议呢qwq

for i in taichi.static(range(2,m-2)):
        templist[0,i]=RK4_L2(0.0,end,step,i)

因为你用了 ti.static 以后这个循环会在编译时被展开。

ti.static 的目的是将一些小而紧凑的for 循环展开,从而节省用于 loop 条件判断的指令。但是如果你的循环体很复杂的话,这个展开会增加编译时间。

非常感谢! 错误理解了static的用法,现在已经解决了

1 个赞

(借用一下楼主的贴子)您好,taichi的自动微分您了解吗,貌似涉及到累加的操作需要用ti.static。但是我的循环体展开次数太多了,用ti.static计算效率会很低。不知道自动微分的时候是否可以不用ti.static?