0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

新しいdarknet

0
Posted at

こういう構想を温めている。

darknet — 推論特化フォーク

darker than darknet — 上流より依存が少なく(暗く)、ビット深度も暗い(int8)。

Darknet/YOLO(Stéphane Charette 版)からフォークした、
組み込み用途に特化した推論エンジンです。上流が「学習からアノテーション、デモまで揃った
CV ワークベンチ」を目指すのに対して、このフォークは他人のアプリケーションに埋め込まれる
推論部品
として最適化しています。

特徴

  • OpenCV 非依存 — 推論側は OpenCV を一切リンクしません。画像の decode / 配管はホスト側
    (Windows: GDI+/D3D11、Linux: GStreamer、組み込み: 任意)に任せ、エンジンは
    「interleaved 8bit + stride」の生バッファ契約だけを持ちます。dll は約 0.7MB。
  • 狭い C ABI(14 関数) — opaque handle + プリミティブ型のみ。C++ 型・コールバック・
    所有権の受け渡しなし。C# ラッパーと GStreamer プラグインはこの ABI 経由で実運用中。
    Python(ctypes)と C# のサンプル(src-examples-py/ / src-examples-cs/)が
    束縛の実例で、他の FFI 言語(Java の FFM / jextract 等)も同じ距離感で繋がります。
  • INT8 量子化(PTQ)を CPU / GPU 両対応で内蔵 — 独自の .i8 フォーマット
    (DI8_FORMAT.md、凍結仕様)。較正器もエンジンに内蔵
    (dn_calib_accumulate / dn_calib_write_i8)。
    • CPU: oneDNN(AVX2-VNNI / AVX512-VNNI の brgemm カーネル)。u8 チェーンで
      レイヤー間の量子化往復を省略。
    • GPU: cudnn-frontend の fused int8 conv + s8 パススルーチェーン
      (maxpool / route / upsample が s8 のまま流れる)。
  • GPU 推論の近代化 — cudnn-frontend fused conv(conv+bias+act 融合、mish/SiLU 対応)、
    CUDA Graph capture、YOLO デコードの GPU 化(候補のみ D2H 転送)、CUDA デバイスメモリ
    直接入力(dn_detect_rgb_gpu、GStreamer GstCudaMemory 等からゼロコピー)。
  • 省 VRAM — 遅延 fp16 変換・共有ワークスペース・NCHW elision 等で、
    LPR モデル(tiny-3l 1280×736)の常駐 VRAM を 1435MB → 561MB(−61%)。
  • ONNX エクスポート内蔵 — fp32 / fp16 に加え、QDQ 形式の int8 ONNX
    (ONNX Runtime で QLinearConv に融合)と、TensorRT / DLA 向けの -s8 対称版。
  • モデル互換 — 上流 darknet の .cfg / .weights / .names をそのまま読みます。
    学習は上流(または本フォークの学習側ツリー)で行い、成果物を無変換で配備できます。
    YOLOv3 世代の既存資産も再学習ゼロで復活します — 較正数分で .i8 化(実測 int8 税 0.2pt、
    GPU 6.2ms/162fps @608)と int8 ONNX 化(leaky は QLinearConv に完全融合)が通ります。

実測値(参考)

COCO val2017 mAP vs レイテンシ(同一マシン実測)

伝統のグラフです。ただし一点だけ流儀が違います — 全点を同一マシンで実測しています
(YOLO26 の mAP のみ公称値)。2021 年製の yolov4-csp-swish が、全段 INT8(DI8)+
cudnn-frontend 融合 conv + CUDA Graph の研ぎで、現行世代と同じ速度帯に立ちます。
COCO の再学習は一切していません — 既製の重みを較正しただけです。

経路 機材 モデル 結果
CPU int8 (oneDNN) i7-12650H (AVX2-VNNI) tiny-3l 1280×736 51.5ms/枚 = fp32 比 3.13×
GPU int8 (fe + s8 chain + GPU decode) RTX 4060 Laptop 同上 1.90ms / 525fps(f16 起点 1.7×)
GPU 多レーン RTX 4060 Laptop 同上 ×4 ストリーム 集約 ~430fps、VRAM 計 555MB

読み取り精度は全量オラクル A/B(11 万枚超)で fp32 とほぼ完全一致(実誤読差 0.013%)を確認済み。

リポジトリ構成

src-lib/            エンジン本体(darknet_capi.h = 公開 C ABI、darknet_abi.def = 公開シンボル)
src-cli-inference/  darknet_detect CLI(検出・ベンチ・fp16/int8 エクスポート)
src-examples-py/    C ABI サンプル(Python / ctypes 束縛 dn.py + 上流サンプル対応番号)
src-examples-cs/    C ABI サンプル(C# / P-Invoke + GDI+、上流サンプル対応番号)
int8_check/         INT8 検証・ベンチ・ONNX エクスポータのツール群
DI8_FORMAT.md       .i8 フォーマット仕様(凍結)

C ABI サンプルは上流 src-examples/(C++ / OpenCV)のラインナップに番号を揃えた
別実装で、Python・C# とも 01-08 / 11 / 12 を揃えています(09-10 の keypoints は
エンジン対応外のため対象外): 01=静止画推論+注釈保存 / 02=静止画表示 / 03・04=動画表示・処理 /
05=マルチスレッド(ハンドル並列の掟と DN_INFER_THREADS の按分の実演)/ 06=JSON 出力 /
07・08=RTSP・webcam / 11=YOLO 形式の自動アノテーション / 12=フォーク独自の
ffmpeg パイプサンプル。

フロントエンドの流儀が言語で異なるのが見どころです:

  • Python — 表示・動画系は opencv-python(デコード/表示のフロントエンド役。エンジン自体は
    OpenCV-free のまま)、12 のみ ffmpeg パイプ + Pillow。
  • C# — OpenCV 完全不使用。動画の decode/encode は ffmpeg パイプ(bgr24 は GDI+ の
    24bpp と同じ並びなので dn_detect_rgb へ無変換直渡し)、動画表示は ffplay への
    パイプ(03/07/08、12 の --play)、静止画表示(02)は sixel でターミナル内に
    インライン描画(Windows Terminal 1.22+ 等)。GUI ツールキット不要でウィンドウも
    ターミナル画像も出せます。

12 の入力は ffmpeg が読めるもの全部(ファイル / rtsp:// / dshow デバイス)。
05 は複数ハンドル並列時の掟(スレッド毎ハンドル + DN_INFER_THREADS の按分、
C# はネイティブ側に届く SetEngineEnv 経由)を実演します。.weights の代わりに .i8 を
渡せばそのまま INT8 で走ります。エンジン自体は OpenCV-free のまま — 表示・動画系
サンプルの opencv-python はデコード/表示のフロントエンド役で、これは ABI が呼び出し側に
委ねている役割そのものです。

周辺エコシステム(別リポジトリ): C# ラッパー、GStreamer プラグイン
(darknetinfer / darknetoverlay、共有エンジン refcount 方式)、TFLite コンバータ、
ブラウザ完結の int8 ONNX デモ。

C ABI 最小例

#include "darknet_capi.h"

dn_handle h;
if (dn_create("model.cfg", "model.i8", "model.names", /*gpu=*/0, &h) != 0) { /* dn_last_error() */ }

dn_box boxes[64]; int n = 0;
dn_detect_rgb(h, pixels, width, height, /*channels=*/3, /*stride_bytes=*/0,
              DN_PIXEL_RGB, /*threshold=*/0.25f, /*nms=*/0.45f,
              boxes, 64, &n);
/* boxes[0..n) を使う */

dn_destroy(h);
  • .weights を渡せば fp32、.i8 を渡せば int8 で動きます(magic sniff で自動判別)。
  • 1 ハンドルは 1 スレッド専用。複数ストリームはハンドルを分けてください
    (CPU は真に並列、GPU は内部でエンジンロックにより直列化)。
  • 同一プロセスでの GPU / CPU ハンドル混在は非対応です。

ビルド

2 つの構成があります。CMake の既定は上流同等のフル構成
(学習 + OpenCV + 元の CLI + サンプルプログラム 11 本)で、上流のワークフローがそのまま再現できます。
推論特化構成は -DDARKNET_INFERENCE_ONLY=ON(さらに OpenCV を切るなら
-DDARKNET_USE_OPENCV=OFF)で、サンプルと元 CLI の代わりに OpenCV 非依存の
darknet_detect CLI がビルドされます。以下は推論特化構成の例です。

Windows (VS2022)

"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
cmake --build build_onednn --config Release --target darknet   & rem CPU (oneDNN) -> darknet_cpu.dll
cmake --build build_gpu    --config Release --target darknet   & rem GPU (CUDA)   -> darknet_gpu.dll

注意: darknet_detect.exe は同一ディレクトリの dll をロードします。ビルド後は
src-lib\Release\darknet_*.dll を exe 側へコピーしてください(古い dll が残っていると
コード変更が反映されない「stale-dll 罠」を踏みます)。

注意: int8(.i8)を実行するビルドは oneDNN リンクが必須です。oneDNN 非リンクの
ビルドに .i8 を渡すと、警告なく fp32 実行に落ちます。

Linux

通常の CMake ビルドで、CPU(oneDNN)/GPU(CUDA + cudnn-frontend)とも同一ソースが通ります。

実行時トグル(環境変数)

変数 既定 意味
DN_INFER_THREADS P-core 数 CPU 推論スレッド数
DN_DISABLE_INT8=1 off .i8 を同解像度の fp32 として実行(切り分け用)
DN_I8_CHAIN=0 / DN_I8_CHAIN2=0 on CPU u8 チェーン最適化の段階的オプトアウト
DN_FE_CONV=0 on GPU fused-conv(cudnn-frontend)経路の無効化
DN_FE_CUDAGRAPH=0 on CUDA Graph capture の無効化
DN_FE_PLAN_CACHE on プランキャッシュ + tune-on-miss。既定でモデルの隣に <weights>.plans.tsv を作り、初回起動時に最適エンジンプランを実測選定(~1 分/モデル)して保存、以後の起動は +1.5s 程度で再生します。=<file> で保存先を指定、=0 でキャッシュと自動チューニングごと無効(ヒューリスティクス選定のみ)
DN_FE_AUTOTUNE=1 off 強制再チューニング(キャッシュを実測で作り直す)。tune-on-miss が既定で効くため通常は不要
DN_GPU_YOLO=0 on YOLO デコードの GPU 実行を無効化(CPU スキャンに戻す)
DN_NMS_PERCLASS=1 off NMS をクラス別に(既定はクラス非依存 = OCR/ANPR 向き)
DN_VERBOSE=1 off CLI の詳細出力

すべての性能系トグルは「未設定 = 最速」に揃えてあります。 環境変数は診断・切り分け・
特殊配備(例: モデル置き場が読み取り専用で .plans.tsv を書けない場合の
DN_FE_PLAN_CACHE=<書き込み可能なパス>)のためのものです。

ベンチマークの流儀

GPU 経路は初回に数秒の初期化(cuDNN・autotune・グラフ capture)を払います。
短いクリップの「総時間 ÷ 枚数」を fps と呼ばないでください。 定常スループットは
ウォームアップ後に計測するか、枚数 2 点の差分で startup を消去して求めます。
darknet_detect --bench は前処理込み、ONNX Runtime 比較時は前処理の扱いの差に注意。

上流との関係

  • 学習器・.cfg / .weights 互換性は上流に追従します(定期的に上流の変更を取り込み)。
  • 本フォークの変更(OpenCV 切除・C ABI・INT8・fe 経路)は上流の設計方針
    (OpenCV 非 optional 化、cv::Mat への統合)と方向が逆のため、上流へのマージは想定していません。
  • ライセンスは上流 Darknet/YOLO のライセンスに従います。

謝辞

Joseph Redmon(原作)、Alexey Bochkovskiy(YOLOv4 系譜と CPU/XNOR 最適化)、
Stéphane Charette(現行上流のモダナイズと保守)。この推論エンジンは巨人の肩の上の
小さな暗がりです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?