DifferentialEquations.jl library เป็นไลบรารี่สำหรับภาษาระดับสูง (Julia) ซึ่งมีเครื่องมือสำหรับเปลี่ยนระบบ ODE ให้เป็นเวอร์ชั่นที่ปรับให้เหมาะสมโดยอัตโนมัติสำหรับโซลูชั่นแบบขนานบน GPU มีสองรูปแบบของการขนานที่สามารถใช้ได้คือ: ขนานตามอาร์เรย์สำหรับระบบ ODE ขนาดใหญ่และขนานพารามิเตอร์สำหรับการศึกษาพารามิเตอร์ในระบบที่ค่อนข้างเล็ก (<100) ODE รองรับวิธีการสั่งโดยปริยายและชัดเจนและมีประสิทธิภาพเหนือกว่าหรือตรงกับระบบอื่น ๆ ในเกณฑ์มาตรฐาน (อย่างน้อยที่สุดมันจะห่อหุ้มระบบอื่น ๆ เพื่อให้ง่ายต่อการตรวจสอบและใช้งาน!)
สำหรับฟังก์ชั่นเฉพาะนี้คุณอาจต้องการดูDiffEqGPU.jlซึ่งเป็นโมดูลสำหรับการขนานพารามิเตอร์อัตโนมัติ ไลบรารี DifferentialEquations.jl มีฟังก์ชันสำหรับการศึกษาพารามิเตอร์แบบขนานและโมดูลนี้จะเพิ่มการกำหนดค่าที่มีอยู่เพื่อให้การศึกษาเกิดขึ้นโดยอัตโนมัติในแบบคู่ขนาน สิ่งที่หนึ่งจะแปลงที่มีอยู่ของพวกเขาODEProblem
(หรืออื่น ๆ ที่DEProblem
ชอบSDEProblem
) เป็นEnsembleProblem
และระบุด้วยprob_func
วิธีการสร้างปัญหาอื่น ๆ จากต้นแบบ ต่อไปนี้จะแก้ปัญหาการโคจรของสมการ Lorenz 10,000 บน GPU ด้วยวิธีการปรับตัวที่ชัดเจนในลำดับสูง:
using OrdinaryDiffEq, DiffEqGPU
function lorenz(du,u,p,t)
@inbounds begin
du[1] = p[1]*(u[2]-u[1])
du[2] = u[1]*(p[2]-u[3]) - u[2]
du[3] = u[1]*u[2] - p[3]*u[3]
end
nothing
end
u0 = Float32[1.0;0.0;0.0]
tspan = (0.0f0,100.0f0)
p = (10.0f0,28.0f0,8/3f0)
prob = ODEProblem(lorenz,u0,tspan,p)
prob_func = (prob,i,repeat) -> remake(prob,p=rand(Float32,3).*p)
monteprob = EnsembleProblem(prob, prob_func = prob_func)
@time sol = solve(monteprob,Tsit5(),EnsembleGPUArray(),trajectories=10_000,saveat=1.0f0)
สังเกตุว่าผู้ใช้ไม่จำเป็นต้องเขียนรหัส GPU และด้วย RTX 2080 มาตรฐานเดียวนี้เป็นการปรับปรุง 5 เท่าโดยใช้เครื่อง 16 core Xeon ที่มีความขนานหลายเธรด หนึ่งแล้วสามารถตรวจสอบไฟล์ README สำหรับวิธีการที่จะทำสิ่งที่ต้องการใช้ประโยชน์จากหลาย GPUs และการทำ multiprocessing GPUs + สำหรับใช้คลัสเตอร์เต็มรูปแบบของ GPUs พร้อมกัน หมายเหตุการสลับที่ multithreading แทน GPUs คือการเปลี่ยนแปลงบรรทัดที่หนึ่ง: แทนEnsembleThreads()
EnsembleGPUArray()
จากนั้นสำหรับนักแก้ปัญหาโดยนัยอินเทอร์เฟซเดียวกันถือ ตัวอย่างเช่นต่อไปนี้ใช้ลำดับสูง Rosenbrock และวิธี Runge-Kutta นัย:
function lorenz_jac(J,u,p,t)
@inbounds begin
σ = p[1]
ρ = p[2]
β = p[3]
x = u[1]
y = u[2]
z = u[3]
J[1,1] = -σ
J[2,1] = ρ - z
J[3,1] = y
J[1,2] = σ
J[2,2] = -1
J[3,2] = x
J[1,3] = 0
J[2,3] = -x
J[3,3] = -β
end
nothing
end
function lorenz_tgrad(J,u,p,t)
nothing
end
func = ODEFunction(lorenz,jac=lorenz_jac,tgrad=lorenz_tgrad)
prob_jac = ODEProblem(func,u0,tspan,p)
monteprob_jac = EnsembleProblem(prob_jac, prob_func = prob_func)
@time solve(monteprob_jac,Rodas5(linsolve=LinSolveGPUSplitFactorize()),EnsembleGPUArray(),dt=0.1,trajectories=10_000,saveat=1.0f0)
@time solve(monteprob_jac,TRBDF2(linsolve=LinSolveGPUSplitFactorize()),EnsembleGPUArray(),dt=0.1,trajectories=10_000,saveat=1.0f0)
ในขณะที่แบบฟอร์มนี้ต้องการให้คุณให้ยาโคเบียนเพื่อใช้กับ GPU (ปัจจุบันจะได้รับการแก้ไขในไม่ช้า) เอกสาร DifferentialEquations.jl แสดงให้เห็นถึงวิธีการคำนวณจาโคเบียนสัญลักษณ์อัตโนมัติในฟังก์ชั่นที่กำหนดตัวเลขดังนั้นจึงไม่มีคู่มือ แรงงานที่นี่ ฉันขอแนะนำอัลกอริธึมเหล่านี้อย่างมากเพราะตรรกะการแตกแขนงของวิธีเช่น CVODE โดยทั่วไปทำให้เกิดเธรด desync และดูเหมือนจะไม่ทำงานเช่นเดียวกับวิธี Rosenbrock ในสถานการณ์ประเภทนี้ต่อไป
ด้วยการใช้ DifferentialEquations.jl คุณจะสามารถเข้าถึงไลบรารี่แบบเต็มซึ่งรวมถึงฟังก์ชันการทำงานเช่นการวิเคราะห์ความไวระดับโลกซึ่งสามารถใช้การเร่งด้วย GPU นี้ นอกจากนี้ยังเข้ากันได้กับตัวเลขคู่สำหรับการวิเคราะห์ความไวอย่างรวดเร็วในท้องถิ่น รหัสที่ใช้ GPU ได้รับคุณสมบัติทั้งหมดของ DifferentialEquations.jl เช่นการจัดการเหตุการณ์และชุดแก้ ODE ขนาดใหญ่ซึ่งปรับให้เหมาะกับปัญหาประเภทต่างๆซึ่งหมายความว่าไม่ใช่เพียงตัวแก้ปัญหา ODE แบบ GPU เพียงครั้งเดียว แต่แทนที่จะเป็น ส่วนหนึ่งของระบบที่มีคุณสมบัติครบถ้วนซึ่งยังรองรับ GPU ได้อย่างมีประสิทธิภาพ