Win10, tensorflow-gpu 2.0.0, CUDA 10.0 で CuDNN の初期化に失敗するケースを新たに見つけた
最近 tensoflow を使うために Python を少し触っています。(バージョンは 3.7)
tensorflow の導入で色々ずっこける事が多かったのですが、検索すれば必ず正解が見つかり、前に進むことができていました。
しかし、先日検索しても中々ヒットしない問題に直面しました。今回はそれについてお話します。
目次
状況
僕以外にも出くわす方が多いかもしれませんが、tensorflow で GPU と共に実験しようとしたときに、CuDNN の初期化に失敗する(そして CNN の初期化にも失敗する)ケースがあります。その原因の殆どは CuDNN 自体を入れていないか(僕)、パスを通し忘れているかだと思います。検索すれば手順がたくさん出てきます。
調べた手順で解決して作業を勧めたのですが、またしても同じエラーが発生しました。
Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
{{node model/conv_lst_m2d/while/body/_1/convolution_4}} [Op:__inference_distributed_function_3889]
実装を1行ずつ丁寧に調べた結果、cupy がトリガーとなっていました。当時の利用状況は
- GeForce GTX 1660 Ti 6GB
- Windows 10 Pro
- Python 3.7
- tensorflow-gpu 2.0.0
- CUDA 10.0
- cupy-cuda100 7.6.0
- tensorflow-gpu の CuDNN 初期化前に cupy が import されている
でした。最後のですが、tensorflow-gpu 側の CuDNN 初期化が完了した後では問題なく、inport して両者利用できていました。
解決
tensorflow-gpu と cupy の同居について検索したのですが中々ヒットせず、とりあえず cupy の利用をやめたのですが、先日 cupy のバージョンが 7.7.0 に上がっていたので、試しにアップデートしてみたところ、この問題は出なくなりました。
cupy-cuda100 (7.7.0) - CuPy: NumPy-like API accelerated with CUDA
INSTALLED: 7.6.0
LATEST: 7.7.0
とりあえず古いものを消して、
pip uninstall cupy-cuda100
新しいものを入れる
pip install cupy-cuda100
これでエラーは出なくなりました。
結論
少なくとも CUDA 10.0 で tensorflow-gpu 2.0.0 を使う場合、cupy-cuda100 は最新の 7.7.0 を使えば、当該エラーは発生しないと思う。
(面倒ですからバージョン下げる方は試しませんでした)
所感
今回のは業務とかではなく個人的な利用でしたから「仕方ないから Numpy 使おう」とか「何か更新してるし試してみるかな」という手段が取れました。仕事だと場合によっては面倒な問題ですよね。
検索しても出てこなかったのは、「そんなの自力で解決できて当たり前」「解説するまでもない」「そんな使い方するの?」ということですかね ...。それか単に探し方を間違えただけかも。
仕事で使う場合は、各種バージョンを(時に複数の組み合わせを)試したりして検証しないと問題の言い訳が通らないと思いますが、皆目検討がつかないよりはマシかなと思います。
以上です。
Flutter で Windows アプリを開発するための準備
Flutter でのモバイルアプリ開発はやっていましたが Windows のデスクトップアプリはまだ開発したことがなく、今後やりたいと思った時にいつでも出来るように準備をしましたので、その際の手順をまとめました。いちいちモバイルのエミュレータを立ち上げるのが面倒な時にも便利だと思います。
環境は以下の通りです。
- Flutter : master 1.19.0-2.0.pre.209
- Visual Studio Community 2019 : 16.5.3
手順の一部は以下を参考にしています。
目次
Flutter の設定を変更
Flutter for desktop on Windows を有効にする
以下のコマンドで有効にできます。
>flutter config --enable-windows-desktop
チャンネルを master へ切り替える
stable チャンネルで作業をしていたのですが、Windows アプリの場合は master チャンネルでないとビルドできないようでしたので、切り替えます。
>flutter channel master
flutter devices で PC を認識してくれるか確認
これで、実行端末として自身の PC を認識してくれました。
>flutter devices
必要なツールを取得する
flutter doctor
次のコマンドで必要なツールをダウンロードできます。
>flutter doctor
ただし、私の環境では VC++ のビルドツールに不足がありましたので別途入手しました。
C++ でのデスクトップ開発ツールを入手
Visual Studio Installer を起動して必要な Work load をインストールします。
私の環境では必要なものは以下のとおりです。(doctor コマンドの結果に必要なものがバージョン番号と共に出ています)
利用している Visual Studio のバージョンで変更をします。
表示される画面で「ワークロード」タブから「C++ によるデスクトップ開発」にチェックを入れます。
「個別のコンポーネント」タブへ切り替え、そこで前述の3つのコンポーネントにチェックを入れます。(バージョン間違えに注意)
ツールのパスを通す
以上をインストールし終えたら、環境変数の Path へ以下を追加します。*1
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin
- MSVC
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build
ここまで完了したらパスが通っているか確認します。
再度 flutter doctor
ここまでが問題なく完了できれば、恐らく flutter doctor で怒られることは無いと思います。
いよいよアプリをビルド
書き忘れていましたが、既存のプロジェクトに対しては
> flutter create .
を先にターミナルで実行して desktop 用の準備をしなければなりません。
2020/06/04 追記
既存のプロジェクトがあればそれを、無ければ初期に自動生成されるやつで。(ただし既存のプロジェクトが Windows 版を意識せずモバイルの Native に依存していれば、うまく実行できない可能性はあります)
私は Android Studio を利用しているのでその画面を示しますが、恐らく他の IDE でも同様かと思います。
実行対象のデバイス一覧に Windows (desktop) の文字列が出ているか確認します。出ていなければ他になにか不備があります。flutter doctor の結果を見つつ検索すれば大体の問題は出てきます。(他力本願)
もし最初から IDE を起動していたのであれば、まずは再起動しましょう。
いざビルドラン!
上手くいきました。
参考に出しているアプリは Flutter のアーキテクチャサンプル用に作成したものです。今の所公開はしていません。
最後に
Flutter での Windows アプリの開発をするための準備手順のまとめは以上です。
ここまで読んでくださりありがとうございました。もし記事に何か不備や問題点があればご指定いただけると幸いです。
*1:エディションやバージョンによってパスが異なる可能性があります。
Flutter について自習用メモ 01
しばらく業務で Flutter によるアプリ開発をしていたので、その間に見知ったことを備忘録としてメモしつつ、入門者に伝導する際の台本にできるようなまとめを目指します。自分の言葉で説明できるようになりたいがためです。
最近ではちょっと調べれば大抵の情報は個別に得られるようになりましたが、わかりやすく体系的にまとめた記事がほしいと思いました。
また、ちょっと分かっただけの状態でガリガリ実装したせいでパフォーマンスが著しく悪い結果を生み出す状態も遭遇したことがありますので、その辺も考慮して、「とりあえず使える」ではなく、「実務の中できちんと使える」様になるための具体的な用法をコード例、表示結果とともに(未熟ながら)解説していければと思います。
私自身がモバイルアプリ開発が本業であるため、それを前提とした記事となる見込みです。
目次
概要
Flutter を利用することにより、Android / iOS それぞれに対応したアプリを開発するとなった場合、単一のコードで画面実装(とちょっとしたロジック)を認識共有できる。
メリット、デメリットについては解説しているサイトが沢山あるので省きます。別に Flutter の営業がしたいわけではないのです。
Flutter の導入手順等も省きます。Dart 言語に関する習得は以下のサイトが参考になると思います。
簡単に文法の説明があります。使用する際に必要最低限の知識のエッセンスと言ったところでしょうか。Java や Kotlin、Swift といった言語の知識があれば読み進められると思います。
そこそこ詳細な言語仕様のまとめです。
Dart の試し打ちにはこの Dart Pad が便利です。コアライブラリしか利用できませんが、Dart そのものの学習や、ちょっとしたロジックの検証とかに使えます。
プログラムの実行ルート
基本
デフォルトの設定なら初期に自動で作成される『main.dart』から呼び出されます。
Main クラスが定義されているわけではなくて、main 関数が直に書かれています。*1
後で記載しますが、Widget とは(画面全体も含め) UI 部品のクラスです。
アプリ起動時に何かしたい場合
runApp を呼ぶ前に必要な処理を呼び出せばよいです。
とすれば実現できるし、完全にプラットフォーム独自の処理をするなら Native 層に実装すれば良いです。*2
UI の実装
Flutter ではコードベースで UI 開発
Android も、iOS(今どきならiPadOSも)も Native 開発のときは GUI ベースで好きな UI を画面上に配置して自動で生成してもらえます。(Android なら xml で直接書き込むこともありますね)
Flutter の場合は IDE 上に専用エディターが無く、Dart で直接実装をしていくことになります。
一応 GUI ベースで配置させるツールもあるのですが、個人的には使いづらかったのでおすすめできないです。ただ配置通りにコードを積み重ねていくだけですので、可読性も落ちると思います。
一見するとやりづらそうに思うかもしれませんが、実際にやってみるとそれほど苦にならなかったです。ホットリロードで即座に画面に反映されるからです。常にそれだけで確認できるわけではないですが。*3
最後に
今日のところはここまでにします。暇を見てちょっとずつコンテンツを充実させていきたいです。
基本的なことは少し調べれば情報を得られるようになってきましたが、凝った表現をしようと思うとどう実装すれば実現できるのか中々分からないこともあります。自分が調べて面白いなと思ったものなんかは紹介していきます。
次回からは開発で必要になる各要素についてまとめていきます。
書いた記事が開発者の方の役に立てば幸いです。
Android 7.0 (API 24) への対応 ~(外部)ストレージ内ファイルの共有~
今年最初の技術記事は、開発するアプリを「Android N (API 24) 」へ対応させる過程で苦労したことについて書こうと思います。このバージョンで発生したAndroid側の仕様変更の把握を正確にしていかないと既存のアプリが最新バージョンで安定した動作をできなくなります。弊記事の内容の場合、ビルドのターゲットAPIレベルを「24」としたときに問題が発生します。今回、そのあたりでハマって時間を取られるこを防ぐためにも、備忘録を兼ねて共有していきます。
単純に仕様変更点について知りたいだけなら以下を見ていただければすぐに把握できると思いますが、恐らくそれだけだと対応する際ちょっとした問題にハマる可能性があります。(それとも、そんなのは未熟な私だけですかね?)
Android 7.0 の動作の変更点 | Android Developers
FileProvider | Android Developers
追記:基本的にはGoogleの技術ブログに載っていた方法を参考にしています。URLは......忘れました _(┐「ε:)_
概要
Android 7.0 は Android N とも呼ばれ、Android の現在の最新バージョンです。ちなみに「N」とはコードネーム「Nougat(ヌガー) 」のことです。砂糖菓子です。
このバージョンになってから、ファイルシステム関連のアプリの権限が一段と厳しい仕様となりました。ドキュメントを読んでいくと、その仕様が技術者にとっては全然甘くないことがわかります。弊記事では、このあたりに絞ってまとめていき、どう対処すればいいのか、まとめていきたいと思います。
ファイル共有に関する変更点について
最新のAPIでは、他のアプリとファイルを共有する場合コンテンツプロバイダを介さなければなりません。プライベートファイルのセキュリティを強化するための変更だそうです。では、どのような変更になったのでしょうか。
file://URI の禁止
これまで、URIを使用するときは file://URI を使って処理を実装していました。他のアプリに共有するときなんかはこれをIntentにのせて送信していたわけです。
しかし、これからはこの方法が使えなくなります。
これを使って他のアプリにURIを渡そうとすると FileUriExposedException がトリガーされます。権限を超えてファイルにアクセスしようとしています~と言うような。
なぜそうなるかというと、「URIを受け取る側がそのパスにアクセスする権限を持たない可能性」があるからです。「越権行為は良くない」ということですね!
これからは content://URI
では、どうするか?結論はコンテンツプロバイダのスキーム content:// を使用するということです。実際には ContentProvider のサブクラスである FileProvider を使用します。
今までは Uri.fromFile(File) で取得できるURIを使用していれば良かったのですが、これからは FileProvider.getUriForFile(Context, String, File) でURIを取得します。これにより、当該URIへの一時的なアクセス権限を付与できます。
こうすることにより、共有をされる側のアプリからもそのファイルにアクセスできるわけです。
実装するにはどうするのか
ドキュメント側の記述をよく確認せず実装を試みたことにより、悩みました。
FileProvider を使用してファイルを他のアプリへ提供する場合にはいくつかやらなければならない手順があります。とりあえず、内部ストレージ(getFilesDir()で取得できるディレクトリ内の files/ 以下)のファイルを共有する場合を考えます。
1.FileProvider で共有するファイルのディレクトリを事前に指定
事前に指定されたディレクトリを共有することができます。ですから、まず共有するファイルのディレクトリを指定する必要があります。そのための xmlファイルを作成します。
nameには共有するFileProviderの名前を指定します。好きな名前を指定すれば良いと思います。
ここで使えるタグは以下の3種のみです!それぞれで、設定した path を指定できます。
files-path
これは Context.getFilesDir() で取得できる値 (data/data/{applicationId}/files) を指定する場合に使用します。
cache-path
これは getCacheDir() で取得できる値 (data/data/{applicationId}/cache) を指定する場合に使用します。
external-path
これは Environment.getExternalStorageDirectory() で取得できる値 () を指定する場合に使用します。
生成されるURIはどうなっている?
例えば上記の設定の場合、アプリのドメインが com.kit_lab.android とでも仮定すると
URIは
content://com.kit_lab.android.fileprovider/share_name/{ファイル名}
物理パスは
com.kit_lab.android/files/directory_name/{ファイル名}
となります!
2.AndroidManifest に FileProviderタグを追加
まず、アプリケーションタグの中に FileProvider の定義を追加します。
内容について説明していきます。
android:authorities属性
ここで、アプリのドメインを元にしたURI権限を設定しています。この値はユニークな値であることが望ましいため、大抵は「{アプリのドメイン}.fileprovider」の様な形を設定していますし、Googleの技術ブログでもその様に紹介されていました。
android:exported属性
FileProvider の公開設定です。これは false としておきます。これをパブリックにする必要はないとのこと。
android:grantUriPermissions属性
ファイルへの一時的なアクセス権限を許可するために true を設定します。
meta-data
ここには、前述の xmlファイルを指定します。
3.FileProviderを使用してURIの取得する
ここでようやくURIの取得です。今までは
としていました。しかしこれからは
こうします。なお、先程説明した ContentProvider に指定できるパスの設定時のタグ3種ですが、あそこで指定できるパス以外や存在しないパスでURIを取得しようとすると、
「java.lang.IllegalArgumentException: Failed to find configured root that contains {問題のパス}」
という様な例外がトリガーされます。
getUriForFile の第二引数には先のマニフェストで設定した「android:authorities」の値を指定します。
ここに潜む罠
さて、以上の方法で得たURIをインテントで送信すれば、無事ファイルの共有ができるのですが、SDカード内のファイルを使いたい場合はどうするのでしょうか?
FileProvider に指定するパスの設定時のタグは前述のドキュメントのリンクより、
external-files-path
を指定すれば良さそうです。しかし、これが実際には使えないのです!
では、SDカード内のファイルのURIを取得したくなったらどうすれば良いのでしょうか。
SDカード内のファイルのURIを取得するには
この場合、キャッシュを作成して共有させることにより、例外を発生させることなくファイルを共有できました。
最後に
今回は Android 7.0 での仕様変更の内、ファイルアクセスに関する実装方法について、紹介しましたが、この他にも多くの変更点があり、それにより既存のアプリが影響を受ける可能背が大きいとのことですので、まだちゃんと確認していないという方は一度目を通されたほうが良いです。
また、SDカード内のファイルURI 取得については、使えるディレクトリにキャッシュという方法で対応可能なのがわかりましたが、もっとマシな方法や適切な方法をご存じの方がいらっしゃったら教えていただけたら嬉しいです!
記事に対する意見や質問等もお待ちしております!
とりあえず、これでファイルをSNSやメールで共有できそうな感じです。
では次回投稿をお楽しみに!
改定:04/02/2017
年始の挨拶
新年おめでとうございます
2017年になりました。挨拶が遅れましたが、あけましておめでとうございます。昨年秋からこのブログを始めて、5ヶ月位になりましたが、諸事情によりほとんど更新していませんでした。
今年は、個人的に興味のあったことについての研究開発を沢山進めていきたいですし、そのあたりについても可能な範囲で紹介をしていこうと考えております。
科学技術分野をメインに、今年はしっかりと更新をしていきたいと思っておりますので、よろしくお願い致します。
Unityで覚えるデザインパターン 1 Compositeパターン
趣旨
Unityとは数あるゲームエンジンの中の1つです。
ここ数年、Unityという単語を目にしない日が無いくらいに世に浸透してきましたね。このUnityのおかげで、今までゲーム開発をしたことのなかった人でも、あるいはプログラミング自体未経験の人でも、気軽に挑戦できるようになりました。
そういった中で、私も二年前よりUnityを使うようになったのですが、その頃の私はクラス設計について大して学んだことが無く、仕事でも大変な思いをしました。元々プログラミングを独学で学んでいた上に、基礎をしっかり身につけずにやっていたのがいけなかったです。
Unityを使ってごく小規模なアプリを作りつつ、デザインパターンに関する私自身の備忘録代わりにするのが主軸になりそうですが、Unityをきっかけにプログラミングをはじめた人にもクラス設計を考える手助けになれば幸いです。
デザインパターンとは
オブジェクト指向での設計における定石をパターンとして一般化したものです。コードを再利用できる資産として残したり、仕様変更を容易にする上でとても大事な考え方です。
大抵は「Gofの23のデザインパターン」というのを指しますが、ここではそれに限らず、幅広く見ていきたいと思います。(とはいえ、最初は主にGofパターンとなるかと思います)
Composite パターン
初めてとなる本記事では、Compositeパターンについて触れたいと思います。
概要
構造に関するパターンの1つ。ディレクトリとファイルの関係のような、階層構造をなす再帰的なデータ構造を設計する際に用いられます。
ファイルはディレクトリの中に格納されますが、ディレクトリもまた別のディレクトリの中に格納できます。つまり、フィルとディレクトリはどちらもディレクトリの子要素になれるのです。このように、ディレクトリとファイルを「同一視」してデータ構造を扱うのがCompositeパターンです。
今回作るもの
簡易的なインベントリ。アイテムディレクトリがあって、その中に消費アイテムと装備アイテムが入っている構造を作ってみます。
作るクラス
- Entry.cs
- GameItemDirectory.cs
- GameItemFile.cs
- CompositePatternTest.cs
クラス説明
Entry.cs
アイテムとアイテムディレクトリの抽象クラスです。
GameItemDirectory.cs
アイテムディレクトリを表すクラスです。Entry.csを継承しています。ディレクトリには子要素が入りますのでそのためのListをフィールドに持っています。また、ディレクトリには要素を追加する機能が必要ですので、16行目にそのためのメソッドを実装しています。
GameItemFile.cs
アイテムを表すクラスです。Entry.csを継承しています。今回は特に機能をつけておりません。
CompositePatternTest.cs
動作確認用のクラスです。今回はただデータ構造のログを出すだけにとどまっています。
動作の確認
以上のクラスを作成後、Hierarchy上に空のGameObjectを作成しそこにCompositePatternTest.csをアタッチします。
これを実行すると以下の様なログが得られると思います。
最後に
今回、アイテムディレクトリとその中のアイテムを例にCompositeパターンについて紹介してみましたが、ではこれでゲームのインベントリが実装できるかといえばできます。しかし、その場合は更に他のデザイパターンを実装するのが良さそうです。それは「Visiterパターン」というものです。
特にゲームのインベントリというものは、大抵その構造は決まっていますので、このパターンが有用なのではないかと思っています。
このパターンは、データ構造とそれらに対する処理を分けて実装するというものです。これについては、また別の機会に紹介したいと思います。
注意事項
この記事の内容は、私が学習したことを自分なりに理解して実装したものです。そのため一部正確性に欠けるかもしれません。何かお気づきの点や気になる点がありましたら、コメントいただけると嬉しいです。
参考書籍
こちらの書籍は、Java言語でのデザインパターンの解説をされていますが、とてもわかり易くまとめられていますので、大変参考になりました。