MoTLab -GO Inc. Engineering Blog-MoTLab -GO Inc. Engineering Blog-

CHART Edge AIライブラリ開発におけるCI/CD紹介

RustCIAI
September 10, 2021

システム開発部 AI基盤グループの廣安です。交通事故削減支援を行う次世代AIドラレコサービス『DRIVE CHART』のAI推論処理を行うEdge AIライブラリの開発やメンテナンスを主業務としています。今回はそのライブラリ開発の品質保証のためにどのようにCI/CDを利用しているかという事例について紹介します。


CI/CDとは

CI/CDとはContinuous Integration/Continuous Deliveryの略で、自動でビルド、テスト、デプロイを行う事で常に本番環境にリリース可能な状態にしておくソフトウェア開発の手法です。CIをサポートするツールとしてAWS CodeBuild、GCP Cloud Build、CircleCI、GitHub Actions、Jenkins等といった多数のツールがあります。

CI/CDをソフトウェア開発に取り込む事で、バグを早期発見できて「いつの間にか動かなくなってしまった」という状況になるのを防いだり、リリースなどを自動で行う事で手作業による人的ミスを減らすといった事ができます。

Edge AIライブラリについて

ライブラリ開発におけるCI/CDの取り組みについて説明する前に、Edge AIライブラリの開発について簡単に説明します。私たちが開発しているEdge AIライブラリは、ドラレコ上で動作するアプリケーションから受け取ったカメラ画像を入力としてAI推論処理を行うという役割を担ってます。アプリはその推論結果を元に脇見運転や一時不停止といった各種リスク運転行動を検知し、ドライバーに警告したり映像記録をするといった動作をします。

ライブラリは下図のようにいくつかの言語で開発しています。カメラ画像を処理してAIモデルの入力として適した形式に変換するモデル前処理と呼ばれる処理、AIモデルの出力から警報判定等で使われる必要な情報を取り出すモデル後処理と呼ばれる処理、警報判定をする処理、といったAI推論を除くコアロジックについてはメモリ安全性や開発のしやすさ等の理由から全てRustで実装しています。

An image from Notion

AIモデル推論処理は既存のC++フレームワークを使っている事から、Rust側でFFIのラッパーを用意してコアロジック側から入力データの受け渡し、推論結果の取得ができるようにしています。またアプリはJavaやC/C++で実装されていますがライブラリとしてはJavaのAPIを用意しており、RustでJava側とJNIでやりとりをするためのラッパーを用意し、アプリ側から呼び出せるようにしています。

Edge AIライブラリにおけるCI/CD

Edge AIライブラリは車載デバイス上で動作するものなので、走行中にバグによってクラッシュするという事が許されず、高いソフトウェア品質が求められます。しかし、手作業で開発/リリースに関わるタスクを実行しているとどこかで抜け漏れが生じます。結果、テストが正常に通っていない不具合を含むライブラリをリリースしてしまったり、古いAPIドキュメントが公開されてアプリケーション側で実装ミスが起きたりする事が考えられます。そのため私たちは各タスクの自動化を進め、CI/CDツールを活用したライブラリの品質保証に取り組んでいます。

ライブラリ開発においてはCI/CDで以下のようなタスクを実行しています。

  • ライブラリのビルド/テスト
  • Linter/Formatterチェック
  • メモリエラー検出
  • カバレッジチェック
  • APIのドキュメント作成
  • 開発用Docker imageのビルド/デプロイ
  • ライブラリのデプロイ

それぞれ何をやっているかを簡単に説明します。

ライブラリのビルド/テストはJavaならばJUnit、Rustではcargo testといったように各言語のテストフレームワークを使ってユニットテストや結合テストを実施しています。スナップショットテストも実施しており、最終的にアプリに渡される結果がコード変更により変わっていないかのチェックもしています。スナップショットテストの取り組みについては以前別のブログにも書いていますので参照してください。

Linter/FormatterチェックはJavaではcheckstyle、Rustではcargo-fmt, cargo-clippyのような各言語ごとのLinter/Formatterのツールを使用したチェックを行っています。

メモリエラー検出はSanitizerというRustのコンパイラオプションから使えるチェックツールを使い、実行時のメモリリークやバッファオーバランといったメモリ関連のエラー検出を行っています。

カバレッジチェックはコア部分であるRustに対してのみ行っており、cargo-tarpaulinという3rdpaty製のOSSツールを使って各テストの実行とカバレッジ率計算を行い、Pull request中のコメントとして表示するようにしています。

APIのドキュメント作成は、公開しているJavaのAPIについてjavadocコマンドを用いてAPIドキュメントのHTMLを生成します。javadocは各API実装コードの直前にAPIの処理概要や引数/戻り値の説明等を特定フォーマットのコメントで記述しておく事で、APIドキュメントを自動生成してくれる生成してくれるツールです。生成されたHTMLはCHART開発チーム全員から見えるサイト上にデプロイしています。

開発用Docker imageのビルド/デプロイは開発用にチームで共通で使っているDocker imageをビルドし、image用のリポジトリにデプロイしています。

ライブラリのデプロイはリリース向けにライブラリのビルドを行い、リポジトリへの登録を行います。リリースバージョンはソースとバージョンを紐付けるためにgitのタグにつける運用としており、タグをpushするとCI/CDがそれを検知し、自動的にそのバージョンのライブラリのデプロイプロセスが走るようにしています。正常終了するとライブラリがデプロイ用のリポジトリにpushされ、slackで通知される仕組みにしています。

各タスクの実行タイミングは、短時間でフィードバックが欲しいPull requestへのコミット時は最低限のテストと静的解析といった時間がかからないタスクを実行し、その他の時間がかかるようなタスクはマージ受け入れチェック時や毎日夜間に実行するなど必要に応じて分けるようにしています。

使用しているCI/CDツール

ライブラリの開発ではGitHub ActionsとAWS CodebuildというCI/CDツールを使用しています。

GitHub Actions

GitHub ActionsはGitHubが提供するツールで、実行したいタスクやその実行タイミングといった情報を所定フォーマットで記述したyamlファイルをリポジトリ内の特定フォルダに配置するだけで簡単に使用する事ができます。タスクはジョブという単位で記述でき、各ジョブは最大20並列まで同時に並行実行する事が可能です。

タスクはGitHubが提供するサーバー上の仮想マシン上で実行され、その実行結果やログはGihubのPull requestのページ等から簡単に参照する事ができます。

また、タスクはシェルのコマンドを使って記述できるほか、Actionというサードパーティが用意した様々な処理を実行する仕組みがあり、これを利用する事で仮想マシン上へ必要なツールをインストールしたり、ビルドのキャッシュをロードしてビルド時間を短縮するといった事ができます。Actionはmarketplaceでカテゴリ別に探すことができ、CI上でやりたい処理を検索して導入する事で自分達で実装しないでも様々な処理を実行するが可能です。

AWS Codebuild

AWS CodebuildはAWSが提供するツールで、実行したいタスクを所定のフォーマットで記述したyamlをリポジトリ上に配置する事で使用できます。こちらについてはGitHub Actionsと異なり、実行するタスクはシェルのコマンドのみで記述します。

実行するタイミングについてはGitHubのウェブフックイベントを実行のトリガーとして利用する事ができ、例えばPull requestのブランチへのコミットがあった時にタスクを実行するような指定が可能です。実行タイミングやyamlのファイルパスはAWS Codebuildのサイト上から設定できます。

CI/CDツールの使い分け

使い分け方ですが、Codebuildは処理が実行されるサーバマシンのスペックが比較的高い事から、Docker imageのビルド等の比較的重めの処理を実行する必要があるタスクの実行に使用しています。また、AWSの他サービスとの親和性も高い事からそういった必要性があるタスクについてもCodebuildを使用する事が多いです。

反対にGitHub Actionsはマシンスペックは高くないですが、並列実行が簡単に記述できる事から、細かいタスクを並列で実行するという用途でよく使っています。また、CI上でやりたい事が既存のActionとして存在するようなケースについても使う事があります。例えば、コードカバレッジはPull requestのページ上で簡単に結果をコメントとして可視化できるようなActionがあった事からGitHub Actions上で実行しています。

まとめ

本記事では、私たちが開発しているEdge AIライブラリ開発におけるCI/CDの取り組み内容について紹介を行いました。

開発規模が大きく複雑になるほどCI/CDの必要性は高いと考えており、導入する事で開発コードの品質が担保でき、手戻りによる余計な手間やストレスから解放されると思います。CI/CDのツールは紹介したものの他にも多くありますが、GitHub Actionsのように導入が簡単なツールもありますので、開発/リリースのサイクルにおいて何らかの課題を抱えているようであれば一度試してみる事をおすすめします。


We're Hiring!

📢
Mobility Technologies ではともに働くエンジニアを募集しています。

興味のある方は 採用ページ も見ていただけると嬉しいです。私たちのチームでもエンジニアを募集しています

Twitter @mot_techtalk のフォローもよろしくお願いします!