実現したいこと
GPUを用いた行列演算において、dot演算子を用いることで少しでもメモリ消費を抑えて高速化したい。
後述する通りdot演算子を使わなければ問題ないが、dot演算子を使わないとメモリ消費量が増えてメモリ不足となるため。
前提
Julia(v1.8.5), CUDA.jl(v4.3.2)を用いています。
また実際のスクリプトでは数万*数万の行列を複数使っており、nn_predict内の処理ももう少し複雑ですが、エラーが発生する最低限のスクリプトとして記載しました。
発生している問題・エラーメッセージ
後述するコードにおいて、p_buf.z2が処理ごとに変化します。
本来は、0.0 → 0.0 → 何らかの値(*) → (*)と同じ値 になってほしいですが
例えば 0.0 → 1.2 → 22 → -8.7 となります。
該当のソースコード
julia
1using CSV, DataFrames 2using CUDA 3using Random, Distributions 4 5Random.seed!(48) 6 7mutable struct TrainParams 8 w::CuArray{Float32, 2} 9 b::CuArray{Float32, 2} 10end 11mutable struct BufParams 12 z1::CuArray{Float32, 2} 13 z2::CuArray{Float32, 2} 14 z3::CuArray{Float32, 2} 15end 16 17function nn_predict(p_buf::BufParams, p1::TrainParams, p2::TrainParams, p3::TrainParams, x_train::CuArray{Float32}) 18 println(sum(p_buf.z2)) 19 p_buf.z1 .= p1.w * x_train .+ p1.b; 20 println(sum(p_buf.z2)) 21 p_buf.z2 .= p2.w* p_buf.z1 .+ p2.b; 22 println(sum(p_buf.z2)) 23 p_buf.z3 .= p3.w * p_buf.z2 .+ p3.b; 24 println(sum(p_buf.z2)) 25 26 return nothing 27end 28 29 30dist = Normal(0, sqrt(2.0f0/1000)) 31x_train = cu(rand(dist, 1000, 10)) 32 33p1 = TrainParams( 34 cu(rand(dist, 1000, 1000)), 35 cu(rand(dist, 1000, 1)) 36 ) 37p2 = TrainParams( 38 cu(rand(dist, 1000, 1000)), 39 cu(rand(dist, 1000, 1)) 40 ) 41p3 = TrainParams( 42 cu(rand(dist, 1000, 1000)), 43 cu(rand(dist, 1000, 1)) 44 ) 45 46buf = CUDA.zeros(1000, 10) 47p_buf = BufParams( 48 buf, 49 buf, 50 buf 51 ) 52 53nn_predict(p_buf, p1, p2, p3, x_train)
試したこと
dot演算子ではなく代入にすれば、きちんと
0.0 → 0.0 → 何らかの値(*) → (*)と同じ値
となります。
また、CUDAを使わず全てArray{}で行うとdot演算子でもきちんと
0.0 → 0.0 → 何らかの値(*) → (*)と同じ値
となります。
質問
前述したようにdot演算子を使わないとメモリ不足になるため出来るだけdot演算子を使いたいのですが
- なぜdot演算子を使うと値が処理ごとに変化するのでしょうか?
- どのように修正すればdot演算子を使っても想定通りの挙動になるのでしょうか?
- もしくはdot演算子を使わなくてもメモリ消費量を抑える方法があれば教えてください
以上です。
よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/10/30 23:54
2023/10/31 00:46
2023/10/31 02:41