Tensorflow: ускорение GPU происходит только после первого запуска - PullRequest
1 голос
/ 12 июля 2019

Я установил CUDA и CUDNN на мою машину (Ubuntu 16.04) вместе с tensorflow-gpu.

Используемые версии: CUDA 10.0, CUDNN 7.6, Python 3.6, Tensorflow 1.14


Это вывод nvidia-smi, показывающий конфигурацию видеокарты.

| NVIDIA-SMI 410.78       Driver Version: 410.78       CUDA Version: 10.0     |
|-------------------------------+----------------------+----------------------+
| 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 960M    On   | 00000000:02:00.0 Off |                  N/A |
| N/A   44C    P8    N/A /  N/A |    675MiB /  4046MiB |      0%   E. Process |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1502      G   /usr/lib/xorg/Xorg                           363MiB |
|    0      3281      G   compiz                                        96MiB |
|    0      4375      G   ...uest-channel-token=14359313252217012722    69MiB |
|    0      5157      C   ...felipe/proj/venv/bin/python3.6            141MiB |
+-----------------------------------------------------------------------------+

Это вывод device_lib.list_local_devices() (вспомогательный метод тензорного потока, показывающий, какие устройства он может видеть), показывающий, что мой графический процессор видим для тензорного потока:

[name: "/device:CPU:0"
  device_type: "CPU"
  memory_limit: 268435456
  locality {
  }
  incarnation: 5096693727819965430, 
name: "/device:XLA_GPU:0"
  device_type: "XLA_GPU"
  memory_limit: 17179869184
  locality {
  }
  incarnation: 13415556283266501672
  physical_device_desc: "device: XLA_GPU device", 
name: "/device:XLA_CPU:0"
  device_type: "XLA_CPU"
  memory_limit: 17179869184
  locality {
  }
  incarnation: 14339781620792127180
  physical_device_desc: "device: XLA_CPU device", 
name: "/device:GPU:0"
  device_type: "GPU"
  memory_limit: 3464953856
  locality {
    bus_id: 1
    links {
    }
  }
  incarnation: 13743207545082600644
  physical_device_desc: "device: 0, name: GeForce GTX 960M, pci bus id: 0000:02:00.0, compute capability: 5.0"
]

Теперь что касается фактического использования графического процессора для вычислений. Я использовал небольшой фрагмент кода, чтобы запустил несколько умноженных матриц на процессорах и на графических процессорах, чтобы сравнить производительность:

shapes = [(50, 50), (100, 100), (500, 500), (1000, 1000), (10000,10000), (15000,15000)]

devices = ['/device:CPU:0', '/device:XLA_GPU:0']

for device in devices:
    for shape in shapes:
        with tf.device(device):
            random_matrix = tf.random_uniform(shape=shape, minval=0, maxval=1)
            dot_operation = tf.matmul(random_matrix, tf.transpose(random_matrix))
            sum_operation = tf.reduce_sum(dot_operation)

        # Time the actual runtime of the operations
        start_time = datetime.now()
        with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as session:
            result = session.run(sum_operation)
        elapsed_time = datetime.now() - start_time

        # PRINT ELAPSED TIME, SHAPE AND DEVICE USED       

Вот сюрприз . Когда я в первый раз запускаю ячейку, содержащую этот блок кода (я на ноутбуке Jupyter), вычисления GPU занимают намного больше времени, чем ЦП :

# output of first run: CPU is faster
----------------------------------------
Input shape: (50, 50) using Device: /device:CPU:0 took: 0.01
Input shape: (100, 100) using Device: /device:CPU:0 took: 0.01
Input shape: (500, 500) using Device: /device:CPU:0 took: 0.01
Input shape: (1000, 1000) using Device: /device:CPU:0 took: 0.02
Input shape: (10000, 10000) using Device: /device:CPU:0 took: 6.22
Input shape: (15000, 15000) using Device: /device:CPU:0 took: 21.23
----------------------------------------
Input shape: (50, 50) using Device: /device:XLA_GPU:0 took: 2.82
Input shape: (100, 100) using Device: /device:XLA_GPU:0 took: 0.17
Input shape: (500, 500) using Device: /device:XLA_GPU:0 took: 0.18
Input shape: (1000, 1000) using Device: /device:XLA_GPU:0 took: 0.20
Input shape: (10000, 10000) using Device: /device:XLA_GPU:0 took: 28.36
Input shape: (15000, 15000) using Device: /device:XLA_GPU:0 took: 93.73
----------------------------------------

Surprise # 2 : Когда я перезапускаю ячейку, содержащую фиктивный код умножения матриц, версия GPU намного быстрее (как и ожидалось):

# output of reruns: GPU is faster
----------------------------------------
Input shape: (50, 50) using Device: /device:CPU:0 took: 0.02
Input shape: (100, 100) using Device: /device:CPU:0 took: 0.02
Input shape: (500, 500) using Device: /device:CPU:0 took: 0.02
Input shape: (1000, 1000) using Device: /device:CPU:0 took: 0.04
Input shape: (10000, 10000) using Device: /device:CPU:0 took: 6.78
Input shape: (15000, 15000) using Device: /device:CPU:0 took: 24.65
----------------------------------------
Input shape: (50, 50) using Device: /device:XLA_GPU:0 took: 0.14
Input shape: (100, 100) using Device: /device:XLA_GPU:0 took: 0.12
Input shape: (500, 500) using Device: /device:XLA_GPU:0 took: 0.13
Input shape: (1000, 1000) using Device: /device:XLA_GPU:0 took: 0.14
Input shape: (10000, 10000) using Device: /device:XLA_GPU:0 took: 1.64
Input shape: (15000, 15000) using Device: /device:XLA_GPU:0 took: 5.29
----------------------------------------

Итак, мой вопрос: Почему только после однократного запуска кода происходит ускорение GPU?

Я вижу, что графический процессор настроен правильно (иначе ускорение вообще не произошло бы). Это из-за каких-то начальных накладных расходов? Нужно ли GPU прогреваться , прежде чем мы сможем их реально использовать?

PS: На обоих запусках (то есть на тех, где GPU был медленнее, и на следующих, где GPU был быстрее), я мог видеть, что использование GPU было 100%, поэтому оно определенно использовалось .

P.S .: Только в самом первом запуске кажется, что GPU не получает поднял . Если затем я запускаю его два, три или несколько раз, все запуски после первого будут успешными (то есть вычисление на GPU быстрее).

1 Ответ

0 голосов
/ 14 июля 2019

Комментарий Роберта Кровеллы заставил меня взглянуть на вещь XLA, которая помогла мне найти решение.

Оказывается, что графический процессор сопоставлен с устройством Tensorflow двумя способами: как устройство XLA и как обычный графический процессор.

Вот почему было два устройства, одно с именем "/device:XLA_GPU:0", а другое "/device:GPU:0".

Все, что мне нужно было сделать , это активировать "/device:GPU:0". Теперь Tensorflow сразу же забирает GPU.

...