[C#]Visual Studio 2022で任意のオブジェクトの変更を通知させるテク
みなさん、こんばんは。ボイラーです。
今回は趣味の作業中に気づいたVisual Studio 2022の便利機能について紹介したいと思います。
※なお、記事の最初の方にディープラーニングの内容を書きましたが、そこは重要ではないので流し読みしてもらっていいと思います。あくまで物語の導入として、書いたことをわかってもらえれば幸いです。
背景
書籍「ゼロから作るDeep Learning (3) フレームワーク編」に掲載されている、著者の斎藤 康毅さんがサンプルとして作られたディープラーニングフレームワークであるDeZeroがあります。私はそれをC#コードベースに移植したDeZero.NETというライブラリを作っています。
そのDeZero.NETの開発中に、畳み込みレイヤーの入力値がバックプロパゲーション時にはDisposeされていてNullReferenceExceptionが発生してしまうという現象が起きていました。
今回はこれをデバッグしている時に、Visual Studio 2022の便利機能を発見し使用したら見事にバグの原因に気づけたという話です。
本編
ディープラーニングにおいては、モデルの学習時にモデルに定義されているアーキテクチャに従って、トレーニングが行われていきます。今回でいうと動画にラベル付けをしてそれを回帰モデルとしてトレーニングします。
今回のモデルのアーキテクチャの主要なコンポーネントは、DCNNModel、BottleneckBlock、ResNet50です。詳細は省きます。
トラブル発生
それでこのモデルのトレーニングを安定稼働させるために、デバッグしては動作確認し、デバッグしては動作確認しというのを繰り返しました。その中のバグの1つに、ResNet50の中には畳み込み層があります。この畳み込み層の入力は、モデルに対する1回の「入力から出力、バックプロパゲーションが完了するまで」の間は記憶されているはずでした。しかし、今回のバグではこれが破棄(Dispose)されていました。
そこで、畳み込み層の入力を代入して保持するタイミングで、バグによって破棄される予定のオブジェクトを見つけました。
arg.Through[0]が今回のバグによって破棄される予定のオブジェクトです。
どうやって、このオブジェクトに対してDisposeメソッドが呼ばれるタイミングを知ることができるでしょうか?
バグの原因調査
私はVisual Studioのローカルウィンドウをぽちぽち右クリックをしてコンテキストメニューに何か有用な機能はないか調べました。
すると、ありました!!!!
「値が変更されたときに中断」というメニューがあるではないですか!!!
これで args.Through[0].NDarray
に null
を代入されるタイミング、すなわちDisposeメソッドが呼ばれる時がわかりそうです。
「値が変更されたときに中断」をクリックします。
すると、args.Through[0].NDarray
が漆黒の●がつきましたね。これで追跡してくれるようです。
その後は「続行」(F5)をしました。
なにやら「データのブレークポイントのヒット」という小窓が出てきましたね。なるほど、これでオブジェクトのプロパティやフィールドに対する代入のタイミングが検知できるというわけですね!これは便利だ!!!
データのブレークポイントのヒット後
その後は簡単です。代入のタイミングがわかったところで、呼び出し履歴ウィンドウを確認して、どの処理によって、悪影響のある代入行為が指図されたかを調べれば良いのです。
呼出履歴の中に...ありますねこれ↓
DisposeAllInputs()
。そう、今回の犯人はこのメソッドです。
しっかり、トレーニング処理中に呼ばれるように仕組まれていました。
これだから、既存のコードのコピペ利用は良くないんだなぁ。
まとめ
Visual Studio 2022の便利機能、「値が変更されたときに中断」機能を物語調で紹介しました。
いかがだったでしょうか。
この機能は役に立ちそうな場面というのは多そうなので、ぜひ使ってあげてください。
そして、知らない人がいたら、この記事を紹介してもらえると私は舞います。
株式会社ラグザイア(luxiar.com)の技術広報ブログです。 ラグザイアはRuby on RailsとC#に特化した町田の受託開発企業です。フルリモートでの開発を積極的に推進しており、全国からの参加を可能にしています。柔軟な働き方で最新のソフトウェアソリューションを提供します。
Discussion