Как оптимизировать время cudaHostAlloc и cudaLaunchKernel в обучении pytorch

#deep-learning #pytorch #profiler

Вопрос:

Я пытаюсь профилировать свою модель с помощью профилировщика pytorch. Я использовал приведенный ниже код для профилирования

 with profile(activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA], record_shapes=True) as prof:
    with record_function("model_inference"):
        output_batch = self.model(input_batch)
print(prof.key_averages().table(sort_by="cpu_time_total", row_limit=10))
 

Выходные данные профилировщика выглядят следующим образом

 -------------------------------------------------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  
                                                   Name    Self CPU %      Self CPU   CPU total %     CPU total  CPU time avg     Self CUDA   Self CUDA %    CUDA total  CUDA time avg    # of Calls  
-------------------------------------------------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  
                                        model_inference         3.17%      83.011ms        63.97%        1.675s        1.675s       0.000us         0.00%     373.844ms     373.844ms             1  
                                            aten::copy_         0.24%       6.333ms        39.93%        1.046s       1.504ms      28.758ms         7.69%      29.035ms      41.777us           695  
                                          cudaHostAlloc        36.02%     943.053ms        36.02%     943.053ms      30.421ms       0.000us         0.00%       0.000us       0.000us            31  
                                       cudaLaunchKernel        35.93%     940.773ms        35.93%     940.773ms      86.619us       0.000us         0.00%       0.000us       0.000us         10861  
                                           aten::repeat         0.04%     979.000us        33.77%     884.170ms      30.489ms       0.000us         0.00%     204.000us       7.034us            29  
                                           aten::conv2d         0.06%       1.481ms         8.71%     228.183ms     695.680us       0.000us         0.00%     145.688ms     444.171us           328  
                                      aten::convolution         0.05%       1.391ms         8.66%     226.702ms     691.165us       0.000us         0.00%     145.688ms     444.171us           328  
                                     aten::_convolution         0.10%       2.742ms         8.61%     225.311ms     686.924us       0.000us         0.00%     145.688ms     444.171us           328  
                                aten::cudnn_convolution         0.53%      13.803ms         8.33%     218.051ms     664.790us     137.822ms        36.87%     137.822ms     420.189us           328  
                                               cudaFree         7.46%     195.373ms         7.46%     195.373ms      48.843ms       0.000us         0.00%       0.000us       0.000us             4  
-------------------------------------------------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  ------------  
Self CPU time total: 2.618s
Self CUDA time total: 373.844ms
 

Я замечаю, что большую часть времени (самостоятельный процессор) занимает cudaHostAlloc И. cudaLaunchKernel Что это cudaHostAlloc за «и cudaLaunchKernel «? Можно ли сократить это время? Если да, то как? Существуют ли какие-либо стандартные операции, которые я пропускаю, что приводит к столь высокому расходу времени?

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

Ответ №1:

Я не эксперт, но я думаю, что cudaLaunchKernel вызывается при каждой операции, выполняемой с помощью cuda. Поэтому я думаю, что вы не можете оптимизировать его.

Если вы построите подробную трассировку https://pytorch.org/tutorials/recipes/recipes/profiler_recipe.html#using-tracing-functionality, вы видите, что он вызывается каждый раз, когда вы выполняете операцию cuda, как здесь, для линейного слоя.

трассировка профилировщика

Одно замечание о выводе вашего профилировщика: aten::copy_ cudaHostAlloc cudaLaunchKernel и aten::repeat все это занимает примерно 40% общего времени процессора. Я думаю, что это может быть связано с ProfilerActivity.CUDA этой операцией записи CUDA, но это также добавляет много процессорного времени для вашей первой профилированной операции CUDA. В моем случае простая torch.ones(1000, device="cuda") операция заняла целую секунду процессорного времени, потому что это была первая операция cuda.

Это может быть проблемой в вашем случае, попробуйте удалить ProfilerActivity.CUDA , а может aten::copy_ cudaHostAlloc cudaLaunchKernel быть, и aten::repeat будет иметь гораздо меньшее процессорное время и исчезнет из таблицы.