気の向くままに辿るIT/ICT/IoT
ハードウェア

AMD Ryzen AIチュートリアルQuark Quantization

ホーム前へ次へ
AMD Ryzen AIソフトウェアって?

AMD Ryzen AIチュートリアルQuark Quantization

AMD Ryzen AIチュートリアルQuark Quantization

2025/04/04

 AMD Ryzen AIソフトウェアとNPUドライバをインストールした自身初購入のミニパソコンRyzen 7 8845HS搭載AOOSTAR GEM12 Pro MAX/Windows 11 Proにamd / RyzenAI-SWをgit cloneしてAI学習するQuark Quantization編。

quark_quantizationの概要

 詳細は、検索しても、なかなか見当たらないのでquark_quantizationルート直下のdocディレクトリのquark_quant_readme.md参照。

 NPU/Neural Processing Unit上でディープラーニングモデルを効率的にデプロイするための量子化の例。

 (ここでは、)AMD QuarkによるQuark Quantizationは、量子化APIを使ったCNN/Convolution Neural Network/畳み込みネットワークモデルの量子化。

 AMD Quarkは、深層学習モデルの量子化を簡素化しつつ、強化するクロスプラットフォームのツールであり、精度を損なうことなく、モデルの最適化、事後訓練・事後学習タイプの量子化技術による量子化後の精度回復支援も行うとのこと。

 このチュートリアルの、おおまなか手順としては、

  1. ResNet50モデルをgithubからダウンロード(download_ResNet.py)
  2. ImageNetデータセットの圧縮ファイルをhugginface.coから会員登録・規約同意の上、手動ダウンロード
  3. プロジェクトルートpath\to\quark_quantization上で圧縮ファイルを展開
  4. 展開されたデータセットを校正し、当該データを保存(prepare_data.py)
  5. 校正済みデータを有効化する量子化パラメータの算出に使い、量子化条件を構成・量子化したモデル保存オリジナルと量子化したモデルサイズと精度を出力(quark_quantize.py --quantize --evaluate)
  6. CPU、NPUそれぞれモデルを実行、floatとCPU/NPUの量子化モデルの推論パフォーマンスのベンチマークを出力(quark_quantize.py --quantize --evaluate --benchmark)
  7. 結果を眺め比較・評価

WindowsでRyzen AI SoftwareチュートリアルQuark Quantizationする前に

 requirement.txtの修正が必要、そうしないとパッケージの不足エラーとは別に依存関係の干渉が発生、順繰りpip install -Uしていっても堂々巡りでハマります。

 修正箇所は、唯一バージョン指定されているonnxiruntimeの少なくともバージョン上限の削除(今となっては下限も不要でしょうが)、少なくとも今日時点では、onnxrutimeのバージョン絡みで依存関係上の警告・エラーが発生、onnxrutime 1.20.1で通りました。

WindowsでRyzen AI SoftwareチュートリアルQuark Quantization

path\to\quark_quantization> conda activate ryzen-ai-1.4.0
(ryzen-ai-1.4.0) path\to\quark_quantization>

 まずは、quicktest時と同様に仮想環境を作って、仮想環境を有効にしてから始めます。

 ryzen-ai-1.4.0は、Ryzen AIソフトウェアのインストール中に指定時、デフォルトのconda仮想環境名、もしくは、それをベースに変更したconda仮想環境名です。

(ryzen-ai-1.4.0) path\to\quark_quantization> pip install -r requirements.txt

 続いて普通は必要のないrequirements.txtの編集と、これによる当該プロジェクトで必要なパッケージのインストール。

 ただ、前述の通り、警告・エラーが表示されるかと。

 その場合、今日時点では、requirements.txt内のonnixruntimeのバージョン指定を外し、一度、pip install -r requirements.txt、エラーが出ると思うのでonnxruntime==1.20.1とバージョン指定してpip install、その後、再度、pip install -r requirements.txtすれば、依存関係を調整してくれつつ、警告・エラーも表示されることなく、インストールが完了しました。

(ryzen-ai-1.4.0) path\to\quark_quantization> cd model
(ryzen-ai-1.4.0) path\to\quark_quantization\models> python download_ResNet.py
(ryzen-ai-1.4.0) path\to\quark_quantization\models> cd ..
(ryzen-ai-1.4.0) path\to\quark_quantization>

 更に訓練前のResNet50モデルをmodels/フォルダにダウンロードするために一度、models/フォルダに移動してpython download_ResNet.pyを実行します。

 次の作業のためにquark_quantizationフォルダに戻っておきます。

Hugging Face Dataset ILSVRC/imagenet-1kダウンロードリスト

 次にHugging FaceのILSVRC/imagenet-1kからval_images.tar.gzファイルをダウンロードします。

 尚、今日時点では、この時、Hugging Faceへの会員登録とログイン後に表示される規約をAccept(許諾)する必要がありました。

 会員登録については、当該ページの少し下に[Log in] or [Sign up]というボタンがあり、登録なら後者をクリックします。

 登録後、同じ位置あたりに規約と[Accept]といったボタンがあると思うのでクリックしてから、その下にあるリストからダウンロードします。

 ちなみにダウンロードリスト自体は、[Sign up]/[Login]/[Accept]する前にも表示されており、チェックもできますが、ログイン後、初回なら規約に[Accept]してからでないとダウンロードできません。

(ryzen-ai-1.4.0) path\to\quark_quantization> mkdir val_data && tar -xzf val_images.tar.gz -C val_data
(ryzen-ai-1.4.0) path\to\quark_quantization> python prepare_data.py val_data calib_data

 プロジェクトルートのquark_quantization上でHugging Faceからダウンロードしたval_images.tar.gzをこのようにval_dataフォルダに展開し、prepare_data.pyを実行、val_dataを処理した結果をcalib_dataというフォルダに保存します。

 ちなみに自身は、これ以前に現時点で、まだ終わっていないyolov8やtorchvision_inferenceもいじっていて後者でval_dataにあたるものをcalib_dataとしてダウンロードしてしまい、「フォルダ分けしてねーじゃん!」エラーを食らっており、ここでダウンロードするまでもなく、そのフォルダをmv、val_dataフォルダとして保存したというのは内緒。

 ということは、もしかして、ここで作ったcalib_dataがそっちで使えるのか?と思ってみたりもしますが、いくつかフォルダを覗いてみてもJpeg画像1つしか入ってなかったりで、はて違うかな?と思ってみたり。

[2025/04/04] やはり、このcalib_dataを使ってみたら、torchvision_inferenceも上手く実行できました。

(ryzen-ai-1.4.0) path\to\quark_quantization>python .\quark_quantize.py --quantize --evaluate
 
[QUARK-INFO]: Checking custom ops library ...
 
[QUARK-INFO]: The CPU version of custom ops library already exists.
 
[QUARK-INFO]: Checked custom ops library.
The configuration of the quantization is Config(global_quant_config=QuantizationConfig(calibrate_method=<PowerOfTwoMethod.MinMSE: 1>, quant_format=<QuantFormat.QDQ: 1>, activation_type=<QuantType.QUInt8: 1>, weight_type=<QuantType.QInt8: 0>, input_nodes=[], output_nodes=[], op_types_to_quantize=[], nodes_to_quantize=[], extra_op_types_to_quantize=[], nodes_to_exclude=[], subgraphs_to_exclude=[], specific_tensor_precision=False, execution_providers=['CPUExecutionProvider'], per_channel=False, reduce_range=False, optimize_model=True, use_dynamic_quant=False, use_external_data_format=False, convert_fp16_to_fp32=False, convert_nchw_to_nhwc=False, include_sq=False, include_rotation=False, include_cle=False, include_auto_mp=False, include_fast_ft=False, enable_npu_cnn=True, enable_npu_transformer=False, debug_mode=False, print_summary=True, ignore_warnings=True, log_severity_level=1, extra_options={'ActivationSymmetric': True}))
[QUARK_INFO]: Time information:
2025-04-09 17:31:31.735959
[QUARK_INFO]: OS and CPU information:
                    system --- Windows
                     node --- gem12promax
                    release --- 10
                    version --- 10.0.26100
                    machine --- AMD64
                   processor --- AMD64 Family 25 Model 117 Stepping 2, AuthenticAMD
[QUARK_INFO]: Tools version information:
                    python --- 3.10.0
                     onnx --- 1.16.1
                  onnxruntime --- 1.18.1
                  quark.onnx --- 0.8+2fc870b
[QUARK_INFO]: Quantized Configuration information:
                  model_input --- models/resnet50.onnx
                 model_output --- models/resnet50_quant.onnx
            calibration_data_reader --- <utils.ImageDataReader object at 0x0000026552E59F00>
             calibration_data_path --- None
                 quant_format --- QDQ
                  input_nodes --- []
                 output_nodes --- []
             op_types_to_quantize --- []
          extra_op_types_to_quantize --- []
                  per_channel --- False
                 reduce_range --- False
                activation_type --- QUInt8
                  weight_type --- QInt8
               nodes_to_quantize --- []
               nodes_to_exclude --- []
             subgraphs_to_exclude --- []
                optimize_model --- True
           use_external_data_format --- False
               calibrate_method --- PowerOfTwoMethod.MinMSE
              execution_providers --- ['CPUExecutionProvider']
                enable_npu_cnn --- True
            enable_npu_transformer --- False
           specific_tensor_precision --- False
                  debug_mode --- False
             convert_fp16_to_fp32 --- False
             convert_nchw_to_nhwc --- False
                  include_cle --- False
                  include_sq --- False
               include_rotation --- False
                include_fast_ft --- False
                 extra_options --- {'ActivationSymmetric': True}
 
[QUARK-INFO]: The input ONNX model models/resnet50.onnx can create InferenceSession successfully
 
[QUARK-INFO]: Obtained calibration data with 3 iters
 
[QUARK-INFO]: Removed initializers from input
 
[QUARK-INFO]: Simplified model sucessfully
 
[QUARK-INFO]: Duplicate the shared initializers in the model for separate quantization use across different nodes!
 
[QUARK-INFO]: Loading model...
 
[QUARK-INFO]: The input ONNX model C:/Users/reg/AppData/Local/Temp/vai.cpinit.2r0x5zld/model_cpinit.onnx can run inference successfully
 
[QUARK-INFO]: optimize the model for better hardware compatibility.
 
[QUARK-WARNING]: The opset version is 17 < 20. Skipping fusing Gelu.
 
[QUARK-INFO]: Start calibration...
 
[QUARK-INFO]: Start collecting data, runtime depends on your model size and the number of calibration dataset.
 
[QUARK-INFO]: Finding optimal threshold for each tensor using PowerOfTwoMethod.MinMSE algorithm ...
 
[QUARK-INFO]: Use all calibration data to calculate min mse
Computing range: 100%|███████████████████████████████████████████████████████████| 123/123 [02:18<00:00, 1.12s/tensor]
 
[QUARK-INFO]: Finished the calibration of PowerOfTwoMethod.MinMSE which costs 144.1s
 
[QUARK-INFO]: Remove QuantizeLinear & DequantizeLinear on certain operations(such as conv-relu).
 
[QUARK-INFO]: Rescale GlobalAveragePool /avgpool/GlobalAveragePool with factor 1.0048828125 to simulate DPU behavior.
 
[QUARK-INFO]: Adjust the quantize info to meet the compiler constraints
 
[QUARK-INFO]: Input pos of pooling layer /avgpool/GlobalAveragePool is 1. Output pos of pooling layer /avgpool/GlobalAveragePool is 4.Modify opos from 4 to 1.
 
[QUARK-INFO]: Adjust the quantize info to meet the compiler constraints
The operation types and their corresponding quantities of the input float model is shown in the table below.
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Op Type       ┃ Float Model        ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Conv         │ 53             │
│ Relu         │ 49             │
│ MaxPool       │ 1             │
│ Add         │ 16             │
│ GlobalAveragePool  │ 1             │
│ Flatten       │ 1             │
│ Gemm         │ 1             │
├──────────────────────┼────────────────────────────┤
│ Quantized model path │ models/resnet50_quant.onnx │
└──────────────────────┴────────────────────────────┘
The quantized information for all operation types is shown in the table below.
The discrepancy between the operation types in the quantized model and the float model is due to the application of graph optimization.
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┓
┃ Op Type      ┃ Activation ┃ Weights ┃ Bias   ┃
┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
│ Conv       │ UINT8(53) │ INT8(53) │ INT8(53) │
│ MaxPool      │ UINT8(1)  │     │     │
│ Add        │ UINT8(16) │     │     │
│ GlobalAveragePool │ UINT8(1)  │     │     │
│ Flatten      │ UINT8(1)  │     │     │
│ Gemm       │ UINT8(1)  │ INT8(1) │ INT8(1) │
└───────────────────┴────────────┴──────────┴──────────┘
Model Size:
Float32 model size: 97.41 MB
Int8 quantized model size: 24.46 MB
Model Accuracy:
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:24<00:00, 40.37it/s]
Float32 model accuracy: Top1 0.800, Top5 0.961
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:50<00:00, 19.72it/s]
Int8 quantized model accuracy: Top1 0.781, Top5 0.956
path\to\quark_quantization
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:50<00:00, 19.69it/s]
Int8 quantized model accuracy (NPU): Top1 0.781, Top5 0.956
 
(ryzen-ai-1.4.0) path\to\quark_quantization>

 「fusing Geluスキップしてるよ」という不明な警告1件があるくらいですね。

Ryzen AI Softwareチュートリアルquark_quantizationのquark_quantization.py --quantize --evalute実行時のCPU使用率100% on 8コア16スレッドなRyzen 7 8845HS|Hawk Point

 尚、ふとタスクマネージャに目をやると、このquark_quantization.py --quantize --evalute実行時のCPU使用率が、なんと100%。

 8コア16スレッドなRyzen 8845HSで...。

(ryzen-ai-1.4.0) path\to\quark_quantization>python .\quark_quantize.py --quantize --evaluate --benchmark
 
[QUARK-INFO]: Checking custom ops library ...
 
[QUARK-INFO]: The CPU version of custom ops library already exists.
 
[QUARK-INFO]: Checked custom ops library.
The configuration of the quantization is Config(global_quant_config=QuantizationConfig(calibrate_method=<PowerOfTwoMethod.MinMSE: 1>, quant_format=<QuantFormat.QDQ: 1>, activation_type=<QuantType.QUInt8: 1>, weight_type=<QuantType.QInt8: 0>, input_nodes=[], output_nodes=[], op_types_to_quantize=[], nodes_to_quantize=[], extra_op_types_to_quantize=[], nodes_to_exclude=[], subgraphs_to_exclude=[], specific_tensor_precision=False, execution_providers=['CPUExecutionProvider'], per_channel=False, reduce_range=False, optimize_model=True, use_dynamic_quant=False, use_external_data_format=False, convert_fp16_to_fp32=False, convert_nchw_to_nhwc=False, include_sq=False, include_rotation=False, include_cle=False, include_auto_mp=False, include_fast_ft=False, enable_npu_cnn=True, enable_npu_transformer=False, debug_mode=False, print_summary=True, ignore_warnings=True, log_severity_level=1, extra_options={'ActivationSymmetric': True}))
[QUARK_INFO]: Time information:
2025-04-09 17:36:41.629036
[QUARK_INFO]: OS and CPU information:
                    system --- Windows
                     node --- gem12promax
                    release --- 10
                    version --- 10.0.26100
                    machine --- AMD64
                   processor --- AMD64 Family 25 Model 117 Stepping 2, AuthenticAMD
[QUARK_INFO]: Tools version information:
                    python --- 3.10.0
                     onnx --- 1.16.1
                  onnxruntime --- 1.18.1
                  quark.onnx --- 0.8+2fc870b
[QUARK_INFO]: Quantized Configuration information:
                  model_input --- models/resnet50.onnx
                 model_output --- models/resnet50_quant.onnx
            calibration_data_reader --- <utils.ImageDataReader object at 0x0000024FF2F4DEA0>
             calibration_data_path --- None
                 quant_format --- QDQ
                  input_nodes --- []
                 output_nodes --- []
             op_types_to_quantize --- []
          extra_op_types_to_quantize --- []
                  per_channel --- False
                 reduce_range --- False
                activation_type --- QUInt8
                  weight_type --- QInt8
               nodes_to_quantize --- []
               nodes_to_exclude --- []
             subgraphs_to_exclude --- []
                optimize_model --- True
           use_external_data_format --- False
               calibrate_method --- PowerOfTwoMethod.MinMSE
              execution_providers --- ['CPUExecutionProvider']
                enable_npu_cnn --- True
            enable_npu_transformer --- False
           specific_tensor_precision --- False
                  debug_mode --- False
             convert_fp16_to_fp32 --- False
             convert_nchw_to_nhwc --- False
                  include_cle --- False
                  include_sq --- False
               include_rotation --- False
                include_fast_ft --- False
                 extra_options --- {'ActivationSymmetric': True}
 
[QUARK-INFO]: The input ONNX model models/resnet50.onnx can create InferenceSession successfully
 
[QUARK-INFO]: Obtained calibration data with 3 iters
 
[QUARK-INFO]: Removed initializers from input
 
[QUARK-INFO]: Simplified model sucessfully
 
[QUARK-INFO]: Duplicate the shared initializers in the model for separate quantization use across different nodes!
 
[QUARK-INFO]: Loading model...
 
[QUARK-INFO]: The input ONNX model C:/Users/reg/AppData/Local/Temp/vai.cpinit.18bzl9jn/model_cpinit.onnx can run inference successfully
 
[QUARK-INFO]: optimize the model for better hardware compatibility.
 
[QUARK-WARNING]: The opset version is 17 < 20. Skipping fusing Gelu.
 
[QUARK-INFO]: Start calibration...
 
[QUARK-INFO]: Start collecting data, runtime depends on your model size and the number of calibration dataset.
 
[QUARK-INFO]: Finding optimal threshold for each tensor using PowerOfTwoMethod.MinMSE algorithm ...
 
[QUARK-INFO]: Use all calibration data to calculate min mse
Computing range: 100%|███████████████████████████████████████████████████████████| 123/123 [02:36<00:00, 1.28s/tensor]
 
[QUARK-INFO]: Finished the calibration of PowerOfTwoMethod.MinMSE which costs 163.2s
 
[QUARK-INFO]: Remove QuantizeLinear & DequantizeLinear on certain operations(such as conv-relu).
 
[QUARK-INFO]: Rescale GlobalAveragePool /avgpool/GlobalAveragePool with factor 1.0048828125 to simulate DPU behavior.
 
[QUARK-INFO]: Adjust the quantize info to meet the compiler constraints
 
[QUARK-INFO]: Input pos of pooling layer /avgpool/GlobalAveragePool is 1. Output pos of pooling layer /avgpool/GlobalAveragePool is 4.Modify opos from 4 to 1.
 
[QUARK-INFO]: Adjust the quantize info to meet the compiler constraints
The operation types and their corresponding quantities of the input float model is shown in the table below.
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Op Type       ┃ Float Model        ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Conv         │ 53             │
│ Relu         │ 49             │
│ MaxPool       │ 1             │
│ Add         │ 16             │
│ GlobalAveragePool  │ 1             │
│ Flatten       │ 1             │
│ Gemm         │ 1             │
├──────────────────────┼────────────────────────────┤
│ Quantized model path │ models/resnet50_quant.onnx │
└──────────────────────┴────────────────────────────┘
The quantized information for all operation types is shown in the table below.
The discrepancy between the operation types in the quantized model and the float model is due to the application of graph optimization.
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┓
┃ Op Type      ┃ Activation ┃ Weights ┃ Bias   ┃
┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
│ Conv       │ UINT8(53) │ INT8(53) │ INT8(53) │
│ MaxPool      │ UINT8(1)  │     │     │
│ Add        │ UINT8(16) │     │     │
│ GlobalAveragePool │ UINT8(1)  │     │     │
│ Flatten      │ UINT8(1)  │     │     │
│ Gemm       │ UINT8(1)  │ INT8(1) │ INT8(1) │
└───────────────────┴────────────┴──────────┴──────────┘
Model Size:
Float32 model size: 97.41 MB
Int8 quantized model size: 24.46 MB
Model Accuracy:
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:24<00:00, 40.25it/s]
Float32 model accuracy: Top1 0.800, Top5 0.961
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:51<00:00, 19.49it/s]
Int8 quantized model accuracy: Top1 0.781, Top5 0.956
path\to\quark_quantization
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:51<00:00, 19.42it/s]
Int8 quantized model accuracy (NPU): Top1 0.781, Top5 0.956
Benchmarking CPU float model:
Average inference time over 100 runs: 19.065837860107422 ms
Benchmarking CPU quantized model:
Average inference time over 100 runs: 44.98124361038208 ms
Benchmarking NPU quantized model:
Average inference time over 100 runs: 45.22308826446533 ms
 
(ryzen-ai-1.4.0) path\to\quark_quantization>

 先の量子化と評価に加え、ベンチマークをとるべく、quark_quantization.py --quantize --evalute --benchmarkを実行してみると最後の数行に結果が表示されました。

 CPUの方は、floatモデルもあって値が小さいので、より速いってことですかね?INT(INT8)と比べるとってこと?量子化モデルの方は、CPU、NPU競ってますね。

 これってホントに競ってるのかな?どっちもCPUってことはないよね?

 そっか、INT8より、Float32の方が精度?が高い?割に大雑把な?INT8でも精度ロス少なめで、かなり頑張れてるでしょってことかな?

Ryzen AI Softwareチュートリアルquark_quantizationのquark_quantization.py --quantize --evalute --benchmark実行時のCPU使用率100%/384MB専有GPUの使用率も高め/Ryzen 7 8845HS|Hawk Point

 量子化と評価の時もそうだったのか、当初、そうでもなかったCPU使用率が最後の方で100%となっていた模様。

 こうしてみると今回は、メモリも結構使ってますね。

 ベンチマークをとっている時に、なぜか、たまたまGPUタブが表示されていたため、判明しただけで詳細未確認というか不明というか...。

 ちなみにGPU0自体は、ほとんど使われていないながら、384MBな[専用GPU]は、常時90%以上使用しているかと思いきや、処理が終わって何もしていなくても同じレベルなので、そういうものなようです。

終わったらconda deactivateを忘れずに

(ryzen-ai-1.4.0) path\to\quark_quantization> conda deactivate
path\to\quark_quantization>

 condaの仮想環境での作業が一通り終わったら、conda deactivate(activateの反対語deactivate)しましょう。

 これを忘れると、たいてい痛い目にあうので要注意。

conda info -e
 
# conda environments
#
 
base                path\to\anaconda3
ryzen-ai-1.4.0      path\to\anaconda3\envs\ryzen-ai-1.4.0

 conda deactivateしたら、都度、conda info -eで[*]のついた仮想環境がないことを確認しておくと安心です。

 なぜなら、一見、作業ディレクトリパス先頭から(ryzen-ai-1.4.0)といった仮想環境の表記が消えてもconda info -eで確認すると、まだ[*]が付いているなんてことがあったり、なぜか、代わりに(base)という仮想環境に入ってしまっていたり、知らずにAnacondaコマンドプロンプトを閉じて戻っても同様だったりすることもあったりするので。

 仮想環境baseになってしまう場合、ディレクトリパス先頭に表示されるとは言え、本来の仮想環境については、deactivateコマンドを実行した確信が手伝うのか、意外と気づかないことも多く...。

 何れにせよ、condaの仮想環境にいることを、知らずに、そのまま作業し続けると何かとハマりやすいので要注意。

2025/04/09 訂正・追記
(ryzen-ai-1.4.0) path\to\quark_quantization> python -m virtualenv .venv
(ryzen-ai-1.4.0) path\to\quark_quantization> .\.venv\Scripts\activate

 ページを分けた関係で改めて書くと、まずは、quicktest時と同様に仮想環境を作って、仮想環境を有効にしてから始めます。

 ここでは、condaではなく、pipを使いますが、pip install virtualenvは既に済んでいるものとします。

(ryzen-ai-1.4.0) path\to\quark_quantization> pip install -r requirements.txt

 続いて当該プロジェクトで必要なパッケージのインストール。

(ryzen-ai-1.4.0) path\to\quark_quantization> cd model
(ryzen-ai-1.4.0) path\to\quark_quantization\model> python download_ResNet.py
(ryzen-ai-1.4.0) path\to\quark_quantization\model> cd ..
(ryzen-ai-1.4.0) path\to\quark_quantization>

 更に訓練前のResNet50モデルを取得するためにmodel/フォルダに移動してpython download_ResNet.pyを実行します。

 次の作業のためにquark_quantizationフォルダに戻っておきます。

Hugging Face Dataset ILSVRC/imagenet-1kダウンロードリスト

 次にHugging FaceのILSVRC/imagenet-1kからval_images.tar.gzファイルをダウンロードします。

 尚、今日時点では、この時、Hugging Faceへの会員登録とログイン後に表示される規約をAccept(許諾)する必要がありました。

 会員登録については、当該ページの少し下に[Log in] or [Sign up]というボタンがあり、登録なら後者をクリックします。

 登録後、同じ位置あたりに規約と[Accept]といったボタンがあると思うのでクリックしてから、その下にあるリストからダウンロードします。

(ryzen-ai-1.4.0) path\to\quark_quantization> mkdir val_data && tar -xzf val_images.tar.gz -C val_data
(ryzen-ai-1.4.0) path\to\quark_quantization> python prepare_data.py val_data calib_data

 プロジェクトルートのquark_quantization上でHugging Faceからダウンロードしたval_images.tar.gzをこのようにval_dataフォルダに展開し、prepare_data.pyを実行、val_dataを処理した結果をcalib_dataというフォルダに保存します。

 ちなみに自身は、これ以前に現時点で、まだ終わっていないyolov8やtorchvision_inferenceもいじっていて後者でval_dataにあたるものをcalib_dataとしてダウンロードしてしまい、「フォルダ分けしてねーじゃん!」エラーを食らっており、ここでダウンロードするまでもなく、そのフォルダをmv、val_dataフォルダとして保存したというのは内緒。

 ということは、もしかして、ここで作ったcalib_dataがそっちで使えるのか?と思ってみたりもしますが、いくつかフォルダを覗いてみてもJpeg画像1つしか入ってなかったりで、はて違うかな?と思ってみたり。

(venv) PS path\to\quark_quantization> python .\quark_quantize.py --quantize --evaluate
Traceback (most recent call last):
 File "path\to\quark_quantization\quark_quantize.py", line 11, in
  from quark.onnx import ModelQuantizer
 
ModuleNotFoundError: No module named 'quark'
(venv) PS path\to\quark_quantization> pip install amd-quark
Collecting amd-quark
 Using cached amd_quark-0.8-py3-none-any.whl.metadata (12 kB)
Collecting ninja (from amd-quark)
 Using cached ninja-1.11.1.4-py3-none-win_amd64.whl.metadata (5.0 kB)
Requirement already satisfied: numpy<=2.1.3 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from amd-quark) (1.26.4)
Requirement already satisfied: onnx>=1.16.0 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from amd-quark) (1.17.0)
Requirement already satisfied: onnxruntime<=1.20.1,>=1.17.0 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from amd-quark) (1.18.1)
Requirement already satisfied: onnxruntime_extensions>=0.4.2 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from amd-quark) (0.14.0)
Collecting onnxruntime_genai (from amd-quark)
 Using cached onnxruntime_genai-0.7.0-cp312-cp312-win_amd64.whl.metadata (689 bytes)
Collecting onnxsim==0.4.36 (from amd-quark)
 Using cached onnxsim-0.4.36-cp312-cp312-win_amd64.whl
Collecting pandas (from amd-quark)
 Using cached pandas-2.2.3-cp312-cp312-win_amd64.whl.metadata (19 kB)
Requirement already satisfied: protobuf in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from amd-quark) (6.30.2)
Requirement already satisfied: rich in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from amd-quark) (14.0.0)
Collecting scipy (from amd-quark)
 Using cached scipy-1.15.2-cp312-cp312-win_amd64.whl.metadata (60 kB)
Collecting sentencepiece (from amd-quark)
 Using cached sentencepiece-0.2.0-cp312-cp312-win_amd64.whl.metadata (8.3 kB)
Requirement already satisfied: tqdm in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from amd-quark) (4.67.1)
Requirement already satisfied: coloredlogs in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from onnxruntime<=1.20.1,>=1.17.0->amd-quark) (15.0.1)
Requirement already satisfied: flatbuffers in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from onnxruntime<=1.20.1,>=1.17.0->amd-quark) (25.2.10)
Requirement already satisfied: packaging in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from onnxruntime<=1.20.1,>=1.17.0->amd-quark) (24.2)
Requirement already satisfied: sympy in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from onnxruntime<=1.20.1,>=1.17.0->amd-quark) (1.13.1)
INFO: pip is looking at multiple versions of onnxruntime-genai to determine which version is compatible with other requirements. This could take a while.
Collecting onnxruntime_genai (from amd-quark)
 Using cached onnxruntime_genai-0.6.0-cp312-cp312-win_amd64.whl.metadata (689 bytes)
Collecting onnxruntime<=1.20.1,>=1.17.0 (from amd-quark)
 Using cached onnxruntime-1.20.1-cp312-cp312-win_amd64.whl.metadata (4.7 kB)
Collecting python-dateutil>=2.8.2 (from pandas->amd-quark)
 Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting pytz>=2020.1 (from pandas->amd-quark)
 Using cached pytz-2025.2-py2.py3-none-any.whl.metadata (22 kB)
Collecting tzdata>=2022.7 (from pandas->amd-quark)
 Using cached tzdata-2025.2-py2.py3-none-any.whl.metadata (1.4 kB)
Requirement already satisfied: markdown-it-py>=2.2.0 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from rich->amd-quark) (3.0.0)
Requirement already satisfied: pygments<3.0.0,>=2.13.0 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from rich->amd-quark) (2.19.1)
Requirement already satisfied: colorama in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from tqdm->amd-quark) (0.4.6)
Requirement already satisfied: mdurl~=0.1 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from markdown-it-py>=2.2.0->rich->amd-quark) (0.1.2)
Collecting six>=1.5 (from python-dateutil>=2.8.2->pandas->amd-quark)
 Using cached six-1.17.0-py2.py3-none-any.whl.metadata (1.7 kB)
Requirement already satisfied: humanfriendly>=9.1 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from coloredlogs->onnxruntime<=1.20.1,>=1.17.0->amd-quark) (10.0)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from sympy->onnxruntime<=1.20.1,>=1.17.0->amd-quark) (1.3.0)
Requirement already satisfied: pyreadline3 in c:\users\reg\ryzenai\ryzenai-sw\tutorial\quark_quantization\venv\lib\site-packages (from humanfriendly>=9.1->coloredlogs->onnxruntime<=1.20.1,>=1.17.0->amd-quark) (3.5.4)
Using cached amd_quark-0.8-py3-none-any.whl (762 kB)
Using cached ninja-1.11.1.4-py3-none-win_amd64.whl (296 kB)
Using cached onnxruntime_genai-0.6.0-cp312-cp312-win_amd64.whl (866 kB)
Using cached onnxruntime-1.20.1-cp312-cp312-win_amd64.whl (11.3 MB)
Using cached pandas-2.2.3-cp312-cp312-win_amd64.whl (11.5 MB)
Using cached scipy-1.15.2-cp312-cp312-win_amd64.whl (40.9 MB)
Using cached sentencepiece-0.2.0-cp312-cp312-win_amd64.whl (991 kB)
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
Using cached pytz-2025.2-py2.py3-none-any.whl (509 kB)
Using cached tzdata-2025.2-py2.py3-none-any.whl (347 kB)
Using cached six-1.17.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: sentencepiece, pytz, tzdata, six, scipy, ninja, python-dateutil, pandas, onnxsim, onnxruntime, onnxruntime_genai, amd-quark
 Attempting uninstall: onnxruntime
  Found existing installation: onnxruntime 1.18.1
  Uninstalling onnxruntime-1.18.1:
   Successfully uninstalled onnxruntime-1.18.1
Successfully installed amd-quark-0.8 ninja-1.11.1.4 onnxruntime-1.20.1 onnxruntime_genai-0.6.0 onnxsim-0.4.36 pandas-2.2.3 python-dateutil-2.9.0.post0 pytz-2025.2 scipy-1.15.2 sentencepiece-0.2.0 six-1.17.0 tzdata-2025.2

 ここまでで準備が整ったので量子化と評価をすべく、PowerShell上でquark_quantization.py --quantize --evaluateを実行します。

 が、ModuleNotFoundError: No module named 'quark'となったのでamd-quarkをpip installして再実行。

(venv) PS path\to\quark_quantization> python .\quark_quantize.py --quantize --evaluate
 
[QUARK-INFO]: Checking custom ops library ...
 
[QUARK-WARNING]: The custom ops library path\to\quark_quantization\venv\Lib\site-packages\quark\onnx\operators\custom_ops\lib\custom_ops.dll does NOT exist.
 
[QUARK-INFO]: Start compiling CPU version of custom ops library.
path\to\quark_quantization\venv\Lib\site-packages\torch\utils\cpp_extension.py:414: UserWarning: Error checking compiler version for cl: [WinError 2] 指定されたファイルが見つかりません。
 warnings.warn(f'Error checking compiler version for {compiler}: {error}')
INFO: Could not find files for the given pattern(s).
 
[QUARK-ERROR]: CPU version of custom ops library compilation failed:Command '['where', 'cl']' returned non-zero exit status 1.
 
[QUARK-WARNING]: Custom ops library compilation failed: CPU version of custom ops library compilation failed:Command '['where', 'cl']' returned non-zero exit status 1..
 
[QUARK-INFO]: Checked custom ops library.
The configuration of the quantization is Config(global_quant_config=QuantizationConfig(calibrate_method=, quant_format=, activation_type=, weight_type=, input_nodes=[], output_nodes=[], op_types_to_quantize=[], nodes_to_quantize=[], extra_op_types_to_quantize=[], nodes_to_exclude=[], subgraphs_to_exclude=[], specific_tensor_precision=False, execution_providers=['CPUExecutionProvider'], per_channel=False, reduce_range=False, optimize_model=True, use_dynamic_quant=False, use_external_data_format=False, convert_fp16_to_fp32=False, convert_nchw_to_nhwc=False, include_sq=False, include_rotation=False, include_cle=False, include_auto_mp=False, include_fast_ft=False, enable_npu_cnn=True, enable_npu_transformer=False, debug_mode=False, print_summary=True, ignore_warnings=True, log_severity_level=1, extra_options={'ActivationSymmetric': True}))
[QUARK_INFO]: Time information:
2025-04-04 18:45:06.563850
[QUARK_INFO]: OS and CPU information:
                    system --- Windows
                     node --- gem12promax
                    release --- 11
                    version --- 10.0.26100
                    machine --- AMD64
                   processor --- AMD64 Family 25 Model 117 Stepping 2, AuthenticAMD
[QUARK_INFO]: Tools version information:
                    python --- 3.12.0
                     onnx --- 1.17.0
                  onnxruntime --- 1.20.1
                  quark.onnx --- 0.8+103c340fe2
[QUARK_INFO]: Quantized Configuration information:
                  model_input --- models/resnet50.onnx
                 model_output --- models/resnet50_quant.onnx
            calibration_data_reader ---
             calibration_data_path --- None
                 quant_format --- QDQ
                  input_nodes --- []
                 output_nodes --- []
             op_types_to_quantize --- []
          extra_op_types_to_quantize --- []
                  per_channel --- False
                 reduce_range --- False
                activation_type --- QUInt8
                  weight_type --- QInt8
               nodes_to_quantize --- []
               nodes_to_exclude --- []
             subgraphs_to_exclude --- []
                optimize_model --- True
           use_external_data_format --- False
               calibrate_method --- PowerOfTwoMethod.MinMSE
              execution_providers --- ['CPUExecutionProvider']
                enable_npu_cnn --- True
            enable_npu_transformer --- False
           specific_tensor_precision --- False
                  debug_mode --- False
             convert_fp16_to_fp32 --- False
             convert_nchw_to_nhwc --- False
                  include_cle --- False
                  include_sq --- False
               include_rotation --- False
                include_fast_ft --- False
                 extra_options --- {'ActivationSymmetric': True}
 
[QUARK-INFO]: The input ONNX model models/resnet50.onnx can create InferenceSession successfully
 
[QUARK-INFO]: Obtained calibration data with 3 iters
 
[QUARK-INFO]: Removed initializers from input
 
[QUARK-INFO]: Simplified model sucessfully
 
[QUARK-INFO]: Duplicate the shared initializers in the model for separate quantization use across different nodes!
 
[QUARK-INFO]: Loading model...
 
[QUARK-INFO]: The input ONNX model C:/Users/reg/AppData/Local/Temp/vai.cpinit.p3g6adap/model_cpinit.onnx can run inference successfully
 
[QUARK-INFO]: optimize the model for better hardware compatibility.
 
[QUARK-WARNING]: The opset version is 17 < 20. Skipping fusing Gelu.
 
[QUARK-INFO]: Start calibration...
 
[QUARK-INFO]: Start collecting data, runtime depends on your model size and the number of calibration dataset.
 
[QUARK-INFO]: Finding optimal threshold for each tensor using PowerOfTwoMethod.MinMSE algorithm ...
 
[QUARK-INFO]: Use all calibration data to calculate min mse
Computing range: 59%|███████████████████████████████████▌            | 73/123 [01:26<01:08, 1.37Computing range: 60%|████████████████████████████████████            | 74/123 [01:30<01:54, 2.34Computing range: 61%|████████████████████████████████████▌            | 75/123 [01:30<01:21, 1.69Computing range: 62%|████████Computing range: 100%|███████████████████████████████████████████████████████████| 123/123 [02:21<00:00, 1.15s/tensor]
 
[QUARK-INFO]: Finished the calibration of PowerOfTwoMethod.MinMSE which costs 146.9s
 
[QUARK-INFO]: Remove QuantizeLinear & DequantizeLinear on certain operations(such as conv-relu).
 
[QUARK-INFO]: Rescale GlobalAveragePool /avgpool/GlobalAveragePool with factor 1.0048828125 to simulate DPU behavior.
 
[QUARK-INFO]: Adjust the quantize info to meet the compiler constraints
 
[QUARK-INFO]: Input pos of pooling layer /avgpool/GlobalAveragePool is 1. Output pos of pooling layer /avgpool/GlobalAveragePool is 4.Modify opos from 4 to 1.
 
[QUARK-INFO]: Adjust the quantize info to meet the compiler constraints
The operation types and their corresponding quantities of the input float model is shown in the table below.
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Op Type       ┃ Float Model        ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Conv         │ 53             │
│ Relu         │ 49             │
│ MaxPool       │ 1             │
│ Add         │ 16             │
│ GlobalAveragePool  │ 1             │
│ Flatten       │ 1             │
│ Gemm         │ 1             │
├──────────────────────┼────────────────────────────┤
│ Quantized model path │ models/resnet50_quant.onnx │
└──────────────────────┴────────────────────────────┘
The quantized information for all operation types is shown in the table below.
The discrepancy between the operation types in the quantized model and the float model is due to the application of graph optimization.
┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┓
┃ Op Type      ┃ Activation ┃ Weights ┃ Bias   ┃
┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
│ Conv       │ UINT8(53) │ INT8(53) │ INT8(53) │
│ MaxPool      │ UINT8(1)  │     │     │
│ Add        │ UINT8(16) │     │     │
│ GlobalAveragePool │ UINT8(1)  │     │     │
│ Flatten      │ UINT8(1)  │     │     │
│ Gemm       │ UINT8(1)  │ INT8(1) │ INT8(1) │
└───────────────────┴────────────┴──────────┴──────────┘
Model Size:
Float32 model size: 97.41 MB
Int8 quantized model size: 24.46 MB
Model Accuracy:
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:28<00:00, 34.87it/s]
Float32 model accuracy: Top1 0.800, Top5 0.961
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:46<00:00, 21.29it/s]
Int8 quantized model accuracy: Top1 0.781, Top5 0.956
path\to\quark_quantization
Evaluating: 100%|██████████████████████████████████████████████████████████████████| 1000/1000 [00:47<00:00, 21.02it/s]
Int8 quantized model accuracy (NPU): Top1 0.781, Top5 0.956
(venv) PS path\to\quark_quantization>

 こちらが、ターミナル上の実行時の生の出力結果で完了はしているものの、hello_worldと全く同じ、[QUARK-ERROR]が1件、[QUARK-WARNING]が3件、[QUARK-INFO]でエラーがあったよ情報が1件ありますね。

 「fusing Geluスキップしてるよ」という不明な警告1件を除き、他は、一連の出来事としてCPU版custom_ops.dllがないよ、ファイルがなくてCPU版cl用のコンパイラのバージョンチェックに失敗したよ、CPU版カスタムopライブラリのコンパイルに失敗しちゃったよ、コマンド['where', 'cl']でエラー出てるよってことな模様。

Ryzen AI Softwareチュートリアルquark_quantizationのquark_quantization.py --quantize --evalute実行時のCPU使用率100% on 8コア16スレッドなRyzen 7 8845HS|Hawk Point

 尚、ふとタスクマネージャに目をやると、このquark_quantization.py --quantize --evalute実行時のCPU使用率が、なんと100%。

 8コア16スレッドなRyzen 8845HSで...。

(venv) PS path\to\quark_quantization> python .\quark_quantize.py --quantize --evaluate --benchmark
...
Benchmarking CPU float model:
Average inference time over 100 runs: 17.674121856689453 ms
Benchmarking CPU quantized model:
Average inference time over 100 runs: 41.34226083755493 ms
Benchmarking NPU quantized model:
Average inference time over 100 runs: 41.6889214515686 ms
(venv) PS path\to\quark_quantization>

 先の量子化と評価に加え、ベンチマークをとるべく、quark_quantization.py --quantize --evalute --benchmarkを実行してみると最後の数行に結果が表示されました。

 CPUの方は、floatモデルもあって値が小さいので、より速いってことですかね?INT(INT8)と比べるとってこと?量子化モデルの方は、CPU、NPU競ってますね。

Ryzen AI Softwareチュートリアルquark_quantizationのquark_quantization.py --quantize --evalute --benchmark実行時のCPU使用率100%/384MB専有GPUの使用率も高め/Ryzen 7 8845HS|Hawk Point

 量子化と評価の時もそうだったのか、当初、そうでもなかったCPU使用率が最後の方で100%となっていた模様。

 こうしてみると今回は、メモリも結構使ってますね。

 ベンチマークをとっている時に、なぜか、たまたまGPUタブが表示されていたため、判明しただけで詳細未確認というか不明というか...。

 ちなみにGPU0自体は、ほとんど使われていないながら、384MBな[専用GPU]は、常時90%以上使用しているかと思いきや、処理が終わって何もしていなくても同じレベルなので、そういうものなようです。

ホーム前へ次へ