Наскоро получих платка NVIDIA Jetson Xavier NX, за да прегледам и напиша някои публикации. Първото е неофициално ръководство за надграждане на Ubuntu 18.04 до най-новия Ubuntu Focal (20.04).

Тук ще направя някои бенчмаркове и ще сравня производителността между Jetson NX и други SBC. Преди известно време направих „сравнителен анализ“ на „някои“ ARM платки, сравнявайки тяхната производителност на Java и други натоварвания. Тук ще направя подобен подход и ще добавя някои GPU и тестове за консумация на енергия и сравнения.

Разбира се, ценовият диапазон варира много, от $79 за Odroid N2 и RockPro64 до $399 за Xavier NX, не можем да очакваме подобна производителност или характеристики. Всички платки бяха настроени с помощта на Debian или Ubuntu и без активиран графичен интерфейс.

За да измеря използването на CPU и GPU, инсталирах jtopот репо jetson-stats. Това е помощна програма, подобна на htop, но извлича статистика на NVIDIA. Приложението може да се инсталира с sudo -H pip install -U jetson-stats и да се изпълнява с sudo jtop.

Отказ от отговорност:Тези тестове и бенчмаркове не са научни и са валидирани в строги лабораторни спецификации. Те бяха направени в моята домашна лаборатория с помощта на инструменти и оборудване с отворен код, налични в маркираното. Също така сравнителните показатели, които използвах, по никакъв начин не са изчерпателни за цялото налично натоварване.

Бързи спецификации на дъската

NVIDIA Jetson Xavier NX

  • CPU: 6-ядрен Carmel Arm 64-bit CPU, 6MB L2 + 4MB L3.
  • GPU: NVIDIA Volta с 384 NVIDIA CUDA ядра и 48 тензорни ядра, плюс 2x NVDLA.
  • 8 GB 128-битова LPDDR4x RAM
  • Gigabit Ethernet

HardKernel Odroid N2

  • Amlogic S922X (4x Cortex-A73 @ 1.8GHz, 2x Cortex-A53 @ 1.9GHz); 12nm fab; Mali-G52 GPU с 6x 846MHz EE.
  • 4GB DDR4 RAM.
  • Gigabit Ethernet

Pine64 RockPro64

  • Rockchip RK3399 Hexa-Core (двоен ARM Cortex A72 и четири ARM Cortex A53) 64-битов процесор и MALI T-860 четириядрен графичен процесор.
  • 4GB LPDDR4 RAM.
  • PCIe x4.
  • Gigabit Ethernet

Използвани сравнителни показатели:

  • SPECjvm2008 — Изтегляне от https://www.spec.org/jvm2008/
  • 7zip бенчмарк — Инсталирайте с apt install p7zip-full
  • Sysbench за тестове на паметта
  • PyTorch и TensorFlow за тестове за машинно обучение

CPU бенчмаркове

7zip

Използвам бенчмарка 7zip като базова линия за повечето платки, тъй като показва производителността на чистия процесор и е добро сравнение между платките.

NVIDIA Jetson Xavier NX

❯ 7z b
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,6 CPUs LE)
LE
CPU Freq: - 64000000 64000000 - 128000000 256000000 512000000 - 2048000000
RAM size:    7763 MB,  # CPU hardware threads:   6
RAM usage:   1323 MB,  # Benchmark threads:      6
Compressing  |                  Decompressing
Dict     Speed Usage    R/U Rating  |      Speed Usage    R/U Rating
         KiB/s     %   MIPS   MIPS  |      KiB/s     %   MIPS   MIPS
22:       9309   466   1945   9057  |     113067   568   1699   9642
23:       9036   454   2026   9207  |     110032   564   1688   9521
24:       9186   465   2122   9877  |     108373   567   1678   9512
25:       9337   469   2275  10661  |     106344   564   1679   9464
----------------------------------  | ------------------------------
Avr:             464   2092   9701  |              566   1686   9535
Tot:             515   1889   9618

Odroid N2

❯ 7z b
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,6 CPUs LE)
LE
CPU Freq:  1597  1763  1797  1796  1795  1786  1792  1792  1791
RAM size:    3713 MB,  # CPU hardware threads:   6
RAM usage:   1323 MB,  # Benchmark threads:      6
Compressing  |                  Decompressing
Dict     Speed Usage    R/U Rating  |      Speed Usage    R/U Rating
         KiB/s     %   MIPS   MIPS  |      KiB/s     %   MIPS   MIPS
22:       5848   525   1083   5690  |     118603   535   1892  10115
23:       5615   530   1080   5722  |     114888   532   1868   9941
24:       5511   539   1099   5926  |     113151   536   1853   9932
25:       5223   540   1105   5964  |     107952   530   1812   9607
----------------------------------  | ------------------------------
Avr:             533   1092   5826  |              533   1856   9899
Tot:             533   1474   7862

RockPro64

❯ 7z b
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,6 CPUs LE)
LE
CPU Freq: 64000000 - - - - - 512000000 - -
RAM size:    3793 MB,  # CPU hardware threads:   6
RAM usage:   1323 MB,  # Benchmark threads:      6
Compressing  |                  Decompressing
Dict     Speed Usage    R/U Rating  |      Speed Usage    R/U Rating
         KiB/s     %   MIPS   MIPS  |      KiB/s     %   MIPS   MIPS
22:       4468   476    913   4347  |      94209   522   1540   8034
23:       4114   473    886   4192  |      92694   525   1528   8021
24:       3965   472    902   4264  |      90617   525   1516   7954
25:       3840   480    913   4385  |      88555   525   1501   7881
----------------------------------  | ------------------------------
Avr:             475    904   4297  |              524   1521   7972
Tot:             500   1213   6135

Тук виждаме, че NVIDIA Jetson NX е с 22% по-бърз от Odroid-N2 и с 56% по-бърз от RK3399 SOC от RockPro64.

Java SPECjvm2008

В миналото сравнявах някои версии на Java на ARM64 и също между някои от моите платки в един и същ бенчмарк и има страхотен баланс за демонстриране на производителността на процесора при множество видове натоварвания.

Тук сравнявам трите платки, достигнали тези показатели:

В този тест виждаме, че средно от множество SPECJvm2008 бенчмаркове AmLogic SOC е с 27% по-бърз от RK3399. NVIDIA Xavier NX е 150% по-бърз от AmLogic и 187% по-бърз от RK3399.

Показатели на паметта

След това тествах производителността на паметта с помощта на sysbench. В тези тестове използвах 1K, 1M блокове с тестове за четене и писане.

Тестовете използват 50%, 100% и 200% количество памет за всяка платка.

Ксавие NX

❯ sysbench --test=memory --memory-block-size=1M --memory-total-size=8G run
sysbench 1.0.18 (using system LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 1
Initializing random number generator from current time
Running memory speed test with the following options:
  block size: 1024KiB
  total size: 8192MiB
  operation: write
  scope: global
Initializing worker threads...
Threads started!
Total operations: 8192 (15042.72 per second)
8192.00 MiB transferred (15042.72 MiB/sec)
General statistics:
    total time:                          0.5421s
    total number of events:              8192
Latency (ms):
         min:                                    0.06
         avg:                                    0.07
         max:                                    0.50
         95th percentile:                        0.08
         sum:                                  532.89
Threads fairness:
    events (avg/stddev):           8192.0000/0.00
    execution time (avg/stddev):   0.5329/0.00

Odroid N2

❯ sysbench --test=memory --memory-block-size=1M --memory-total-size=4G run
sysbench 0.4.12:  multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Doing memory operations speed test
Memory block size: 1024K
Memory transfer size: 4096M
Memory operations type: write
Memory scope type: global
Threads started!
Done.
Operations performed: 4096 ( 1236.33 ops/sec)
4096.00 MB transferred (1236.33 MB/sec)
Test execution summary:
    total time:                          3.3130s
    total number of events:              4096
    total time taken by event execution: 3.3096
    per-request statistics:
         min:                                  0.29ms
         avg:                                  0.81ms
         max:                                  2.31ms
         approx.  95 percentile:               1.57ms
Threads fairness:
    events (avg/stddev):           4096.0000/0.00
    execution time (avg/stddev):   3.3096/0.00

RockPro64

rock64@rockpro64:~$ sysbench --test=memory --memory-block-size=1M --memory-total-size=8G run
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
sysbench 1.0.18 (using system LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 1
Initializing random number generator from current time
Running memory speed test with the following options:
  block size: 1024KiB
  total size: 8192MiB
  operation: write
  scope: global
Initializing worker threads...
Threads started!
Total operations: 8192 ( 7796.96 per second)
8192.00 MiB transferred (7796.96 MiB/sec)
General statistics:
    total time:                          1.0473s
    total number of events:              8192
Latency (ms):
         min:                                    0.12
         avg:                                    0.13
         max:                                    0.68
         95th percentile:                        0.13
         sum:                                 1044.03
Threads fairness:
    events (avg/stddev):           8192.0000/0.00
    execution time (avg/stddev):   1.0440/0.00

По-долу таблица с всички тествани размери на блокове и количество памет.

Xavier има средно 200% по-бърз достъп до паметта в сравнение с RockPro64 и 500% по-бърз от Odroid-N2. Това е обратното, което виждаме в сравнението на CPU, където Odroid-N2 обикновено е по-бърз от RockPro64.

Тестове за машинно обучение

За да тествам GPU ускорението на Cuda, взех примерно приложение от рамката на PyTorch, което е класификацията на изображенията на MNIST. В този случай не направих сравнение с другите ARM платки, тъй като нито една от тях няма GPU. Тестовете бяха направени в самата платка Xavier със и без GPU ускорение за ML работни натоварвания. Това е мястото, където тази дъска блести.

Примерното приложение можете да намерите тук:



Изпълнението се извършва в Docker контейнера, предоставен от NVIDIA, с всички необходими изисквания на PyTorch и инсталирани драйвери. Стартирайте Docker с:

docker run -it --runtime=nvidia --rm -v $(pwd):/work -w /work nvcr.io/nvidia/l4t-pytorch:r32.4.2-pth1.5-py3

Поставете го във файла mnist.py от Gist и изпълнете с time python3 mnist.py. По-долу са резултатите от теста:

С GPU

Първо извадката беше изпълнена с пълна поддръжка на Cuda. Помощната програма jtop осцилира използването на процесора около 30–40%, докато GPU скочи до 1,1 Ghz и осцилира около 40–75%.

root@40cb50bd2bc3:/work/pytorch# time python3 mnist.py --epochs=1
Train Epoch: 1 [0/60000 (0%)] Loss: 2.333409
..
Test set: Average loss: 0.0564, Accuracy: 9802/10000 (98%)
real 0m52.126s
user 1m2.100s
sys 0m8.316s

Изпълних 1 епоха (1 итерация) с командата time python3 mnist.py --epochs=1 и изпълнението отне 52,4 секунди.

Без GPU

Без GPU ускорението, всичките 6 ядра работеха на 1,4 Ghz и 100% през цялото време. GPU остана на 0%, както се очакваше.

root@40cb50bd2bc3:/work/pytorch# time python3 mnist.py --epochs=1 --no-cuda
Train Epoch: 1 [0/60000 (0%)] Loss: 2.311259
..
Test set: Average loss: 0.0520, Accuracy: 9825/10000 (98%)
real 12m59.672s
user 65m59.436s
sys 0m44.076s

Изпълнението на 1 епоха (1 итерация) с команда time python3 mnist.py --epochs=1 --no-cuda отне 12:59.7s. Да, правилно прочетохте, почти 13 минути! Повече от 13 пъти по-дълго от времето на GPU.

За сравнение, изпълнението на същото работно натоварване в моя MacBook Pro 15'' 2018 (2,6 GHz 6-ядрен Intel Core i7) без CUDA GPU на Docker контейнер, работещ във VM с 10 ядра и 6 GB RAM, отне:

> docker run -it --rm -v $(pwd):/work -w /work --rm pytorch/pytorch bash
> time python3 mnist.py --epochs=1
....
real 1m39.388s
user 5m32.886s
sys 1m6.857s

Удивително е, че малък GPU в малък бордов компютър, консумиращ много по-малко енергия, може да изпълни същото работно натоварване за почти половината от времето, отколкото лаптоп от най-висок клас.

TensorFlow 2

За тестовете TensorFlow 2 използвах друга проба от MNIST. Приложението е базирано на този файл, но има нужда от някои корекции. Качих го в този Gist.

Тъй като NVIDIA създава изображения на контейнери само за TensorFlow 1.5, за този тест създадох Dockerfile за TF2. Изображението е изпратено в DockerHub с етикет carlosedp/l4t-tensorflow:r32.4.2-tf1-py3.

Тестовете бяха изпълнени с Docker, използвайки nvidia-runtime за GPU ускорение или без него само за CPU.

Любопитно е, че съм виждал много подобни времена между CPU и GPU изпълнения. Дори отворих „нишка“ във форумите на NVIDIA и опитвайки тези предложения, получих подобни числа.

GPU

Контейнерът се изпълнява с docker run -it --runtime=nvidia --rm -v $(pwd):/work -w /work carlosedp/l4t-tensorflow:r32.4.2-tf2-py3 bash

> python3 mnist.py
...
2020-06-12 19:59:30.666323: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1241] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 3560 MB memory) -> physical GPU (device: 0, name: Xavier, pci bus id: 0000:00:00.0, compute capability: 7.2)
2020-06-12 19:59:32.241779: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcublas.so.10
step: 100, loss: 0.373517, accuracy: 0.898438
step: 200, loss: 0.250729, accuracy: 0.933594
...
Test Accuracy: 0.966400
real 0m52.721s
user 0m51.516s
sys 0m5.936s

ЦП

Контейнерът се изпълнява с docker run -it --rm -v $(pwd):/work -w /work carlosedp/l4t-tensorflow:r32.4.2-tf2-py3 bash

> python3 mnist.py
...
2020-06-12 19:57:30.661145: W tensorflow/stream_executor/platform/default/dso_loader.cc:59] Could not load dynamic library 'libcudart.so.10.2'; dlerror: libcudart.so.10.2: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /usr/local/cuda/lib64:/usr/local/cuda-10.2/targets/aarch64-linux/lib:
2020-06-12 19:57:30.661284: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
step: 100, loss: 0.347883, accuracy: 0.914062
step: 200, loss: 0.248891, accuracy: 0.933594
...
Test Accuracy: 0.964100
real 0m51.953s
user 1m14.548s
sys 0m4.824s

Както се вижда, доста подобни времена. Също така не съм виждал GPU на jtop да надвишава 25–30% при 114Mhz (минимум) в режим GPU. Може би някой с повече познания за TensorFlow и Keras може да ми изпрати обратна връзка.

Консумация на енергия

Jetson Xavier NX консумира около 7,3 W при неактивност и надхвърли 11,7 W при 6-ядрен режим на 1,4 Ghz и 9,6 W при 2-ядрен режим на 1,9 Ghz.

Това е най-малко 1,8 пъти по-висока консумация на енергия при пълно използване и 2,5 пъти по-висока при неактивност в сравнение с Odroid-N2, „прегледан от мен“.

По време на теста на Pytorch MNIST видях пикове от 13,5 W при GPU и 10,2 W само при CPU. Като се има предвид времето, което отне тестът, GPU ускорението си заслужава, тъй като изпълнението му отне 13 пъти по-малко време.

Заключение

Като цяло, платката NVIDIA Jetson Xavier NX е мощна машина с повече процесорна мощност, която съм виждал на повечето ARM SBC. С неговия графичен процесор е отворена нова граница с възможности за обработка на работни натоварвания на машинно обучение в ръба, надхвърлящи обработката на процесора на доста скорошен компютър (MacBook Pro 2018).

Освен това като настолен компютър, Xavier NX е страхотна опция в комбинация с M.2 SSD (за повече производителност и място за съхранение) и може да се използва като ежедневен драйвер за повечето задачи за разработка.

Недостатъкът е неговата цена, поставена доста над повечето SBC на $399, но с производителността на CPU и RAM, GPU, M.2 слот и екосистемата на NVIDIA е в различна категория, близка до това, което би била една ARM работна станция.

Ако имате предложения или идеи за тестове, които да се направят в тези дъски, изпратете ми вашите отзиви в Twitter @carlosedp.