#performance #machine-learning #neural-network #tensorflow #nvidia
#Производительность #машинное обучение #нейронная сеть #tensorflow #nvidia
Вопрос:
Я тренирую модель CNN с помощью tensorflow. Я достигаю загрузки графического процессора только на 60% ( — 2-3%) без больших падений.
Sun Oct 23 11:34:26 2016
-----------------------------------------------------------------------------
| NVIDIA-SMI 367.57 Driver Version: 367.57 |
|------------------------------- ---------------------- ----------------------
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|=============================== ====================== ======================|
| 0 GeForce GTX 1070 Off | 0000:01:00.0 Off | N/A |
| 1% 53C P2 90W / 170W | 7823MiB / 8113MiB | 60% Default |
------------------------------- ---------------------- ----------------------
-----------------------------------------------------------------------------
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| 0 3644 C /usr/bin/python2.7 7821MiB |
-----------------------------------------------------------------------------
Поскольку это карта Pascal, я использую CUDA 8 с cudnn 5.1.5
Загрузка процессора составляет около 50% (равномерно распределено по 8 потокам. i7 4770k), поэтому производительность процессора не должна быть узким местом.
Я использую двоичный формат файла Tensorflow с и читаю с tf.TFRecordReader()
Я создаю пакеты изображений, подобные этому:
#Uses tf.TFRecordReader() to read single Example
label, image = read_and_decode_single_example(filename_queue=filename_queue)
image = tf.image.decode_jpeg(image.values[0], channels=3)
jpeg = tf.cast(image, tf.float32) / 255.
jpeg.set_shape([66,200,3])
images_batch, labels_batch = tf.train.shuffle_batch(
[jpeg, label], batch_size= FLAGS.batch_size,
num_threads=8,
capacity=2000, #tried bigger values here, does not change the performance
min_after_dequeue=1000) #here too
Вот мой цикл обучения:
sess = tf.Session()
sess.run(init)
tf.train.start_queue_runners(sess=sess)
for step in xrange(FLAGS.max_steps):
labels, images = sess.run([labels_batch, images_batch])
feed_dict = {images_placeholder: images, labels_placeholder: labels}
_, loss_value = sess.run([train_op, loss],
feed_dict=feed_dict)
У меня нет большого опыта работы с tensorflow, и я не знаю, где может быть узкое место. Если вам нужны дополнительные фрагменты кода, которые помогут выявить проблему, я их предоставлю.
ОБНОВЛЕНИЕ: результаты теста пропускной способности
==5172== NVPROF is profiling process 5172, command: ./bandwidthtest
Device: GeForce GTX 1070
Transfer size (MB): 3960
Pageable transfers
Host to Device bandwidth (GB/s): 7.066359
Device to Host bandwidth (GB/s): 6.850315
Pinned transfers
Host to Device bandwidth (GB/s): 12.038037
Device to Host bandwidth (GB/s): 12.683915
==5172== Profiling application: ./bandwidthtest
==5172== Profiling result:
Time(%) Time Calls Avg Min Max Name
50.03% 933.34ms 2 466.67ms 327.33ms 606.01ms [CUDA memcpy DtoH]
49.97% 932.32ms 2 466.16ms 344.89ms 587.42ms [CUDA memcpy HtoD]
==5172== API calls:
Time(%) Time Calls Avg Min Max Name
46.60% 1.86597s 4 466.49ms 327.36ms 606.15ms cudaMemcpy
35.43% 1.41863s 2 709.31ms 632.94ms 785.69ms cudaMallocHost
17.89% 716.33ms 2 358.17ms 346.14ms 370.19ms cudaFreeHost
0.04% 1.5572ms 1 1.5572ms 1.5572ms 1.5572ms cudaMalloc
0.02% 708.41us 1 708.41us 708.41us 708.41us cudaFree
0.01% 203.58us 1 203.58us 203.58us 203.58us cudaGetDeviceProperties
0.00% 187.55us 1 187.55us 187.55us 187.55us cuDeviceTotalMem
0.00% 162.41us 91 1.7840us 105ns 61.874us cuDeviceGetAttribute
0.00% 79.979us 4 19.994us 1.9580us 73.537us cudaEventSynchronize
0.00% 77.074us 8 9.6340us 1.5860us 28.925us cudaEventRecord
0.00% 19.282us 1 19.282us 19.282us 19.282us cuDeviceGetName
0.00% 17.891us 4 4.4720us 629ns 8.6080us cudaEventDestroy
0.00% 16.348us 4 4.0870us 818ns 8.8600us cudaEventCreate
0.00% 7.3070us 4 1.8260us 1.7040us 2.0680us cudaEventElapsedTime
0.00% 1.6670us 3 555ns 128ns 1.2720us cuDeviceGetCount
0.00% 813ns 3 271ns 142ns 439ns cuDeviceGet
Комментарии:
1. Во-первых, насколько велика ваша партия ? И насколько велика ваша модель? Не могли бы вы попробовать создать больший CNN (и поместить больше данных в один пакет), чтобы увидеть, не связана ли проблема с синхронизацией между CPU и GPU?
2. @lejlot он уже в значительной степени использует память графического процессора
3. @FranckDernoncourt Tensorflow всегда занимает как можно больше памяти графического процессора, если вы ее не настраиваете.
4. @lejlot В моем пакете 32 изображения размером 200x66x3, это 5 Мб, если я не перепутал вычисления! Однако я также пробовал с 128 пакетами, и это ничего не изменило!! Размер модели довольно сложно рассчитать… Я получил 5 сверточных слоев и 3 полностью подключенных..
5. @andre_bauer Спасибо, я не знал об этом.
Ответ №1:
Получив еще немного опыта работы с tensorflow, я понял, что использование графического процессора сильно зависит от размера сети, пакета и предварительной обработки. Использование более крупной сети с большим количеством уровней conv (например, в стиле Resnet) увеличивает использование графического процессора, поскольку требуется больше вычислений и меньше накладных расходов (по отношению к вычислениям) за счет передачи данных и т.д.
Комментарии:
1. Это точно. Эксперименты с сетевыми уровнями, типом, размером пакета и даже точностью с плавающей точкой приведут к различным показателям использования графического процессора.
Ответ №2:
Одним из потенциальных узких мест является использование шины PCI Express между центральным процессором и графическим процессором при загрузке изображений на графический процессор. Вы можете использовать некоторые инструменты для ее измерения.
Еще одним потенциальным узким местом является дисковый ввод-вывод, я не вижу в вашем коде ничего, что могло бы вызвать это, но всегда полезно следить за этим.
Комментарии:
1. Каков наилучший способ проверить наличие узких мест ввода-вывода на диске? Я использую SSD, а данные представляют собой двоичный файл. Если это узкое место, я думаю, что нет способа улучшить :/
2. @andre_bauer Я использую
iotop
в Linux.3. У меня есть 1,7 ГБ (на данный момент) обучающих данных, а диск полностью простаивает, потому что я думаю, что все находится в оперативной памяти (32 ГБ, так что есть место для большего количества обучающих данных!)
4. Я обновил свой вопрос и добавил результаты теста пропускной способности. Я думаю, они выглядят нормально, верно?
5. @andre_bauer да. Жаль, что у нас нет программы для мониторинга использования шины PCI Express в Linux.