当 运行 Numba 代码在 CUDA GPU 上时,我注意到我的 CPU 核心之一保持在 100%。这是限制性能吗?
When running Numba code on a CUDA GPU, I notice one of my CPU cores stays at 100%. Is this limiting performance?
我有一个计算量很大的测试代码,我 运行 在 GPU 上使用 Numba。我注意到虽然那是 运行ning,但我的一个 CPU 核心达到 100% 并一直保持在那里。 GPU 似乎也是 100%。您可以在下面的屏幕截图中看到两者。
我的基准代码如下:
from numba import *
import numpy as np
from numba import cuda
import time
def benchmark():
input_list = np.random.randint(10, size=3200000).astype(np.intp)
output_list = np.zeros(input_list.shape).astype(np.intp)
d_input_array = cuda.to_device(input_list)
d_output_array = cuda.to_device(output_list)
run_test[32, 512](d_input_array, d_output_array)
out = d_output_array.copy_to_host()
print('Result: ' + str(out))
@cuda.jit("void(intp[::1], intp[::1])", fastmath=True)
def run_test(d_input_array, d_output_array):
array_slice_len = len(d_input_array) / (cuda.blockDim.x * cuda.gridDim.x)
thread_coverage = cuda.threadIdx.x * array_slice_len
slice_start = thread_coverage + (cuda.blockDim.x * cuda.blockIdx.x * array_slice_len)
for step in range(slice_start, slice_start + array_slice_len, 1):
if step > len(d_input_array) - 1:
return
count = 0
for item2 in d_input_array:
if d_input_array[step] == item2:
count = count + 1
d_output_array[step] = count
if __name__ == '__main__':
import timeit
# make_multithread(benchmark, 64)
print(timeit.timeit("benchmark()", setup="from __main__ import benchmark", number=1))
如果安装了 python 3.7、Numba 和 codatoolkit,则可以 运行 重现上面的代码。我在 Linux Mint 20。
我有 32 个内核 - 一个 100% 占用而其他人都闲着似乎不太对。
我想知道为什么会这样,是否有办法让其他内核帮助提高性能?
我如何调查是什么占用了 100% 的单核并了解发生了什么?
从主机线程的角度来看,CUDA 内核启动(和一些其他操作)是异步。正如您所说,您是 运行 GPU 工作的计算密集型部分。
因此主机线程除了启动一些工作并等待它完成外,无事可做。这里的等待过程是一个 spin-wait 这意味着 CPU 线程处于紧密循环中,等待状态条件改变。
CPU 线程将在此处触发自旋等待:
out = d_output_array.copy_to_host()
这是内核启动后的代码行,它期望将(有效的)结果从 GPU 复制回 CPU。为了使其工作,CPU 线程必须在那里等待,直到结果准备就绪。 Numba 在 GPU 和 CPU activity 之间通过 阻塞 同步操作实现了这一点。因此,在程序的大部分时间里,CPU 线程实际上在该行代码处等待。
此等待占用该线程的 100% activity,因此一个核心被视为已充分利用。
没有任何意义或理由尝试将此“工作”“分发”给多个 threads/cores,因此这不是您建议的“性能”问题。
任何显示热点或使用 PC 采样的 CPU 分析器都应该能够为您提供这方面的图片。该行代码应该显示在您的 CPU/core/thread.
最常访问的代码行列表的顶部附近
我有一个计算量很大的测试代码,我 运行 在 GPU 上使用 Numba。我注意到虽然那是 运行ning,但我的一个 CPU 核心达到 100% 并一直保持在那里。 GPU 似乎也是 100%。您可以在下面的屏幕截图中看到两者。
我的基准代码如下:
from numba import *
import numpy as np
from numba import cuda
import time
def benchmark():
input_list = np.random.randint(10, size=3200000).astype(np.intp)
output_list = np.zeros(input_list.shape).astype(np.intp)
d_input_array = cuda.to_device(input_list)
d_output_array = cuda.to_device(output_list)
run_test[32, 512](d_input_array, d_output_array)
out = d_output_array.copy_to_host()
print('Result: ' + str(out))
@cuda.jit("void(intp[::1], intp[::1])", fastmath=True)
def run_test(d_input_array, d_output_array):
array_slice_len = len(d_input_array) / (cuda.blockDim.x * cuda.gridDim.x)
thread_coverage = cuda.threadIdx.x * array_slice_len
slice_start = thread_coverage + (cuda.blockDim.x * cuda.blockIdx.x * array_slice_len)
for step in range(slice_start, slice_start + array_slice_len, 1):
if step > len(d_input_array) - 1:
return
count = 0
for item2 in d_input_array:
if d_input_array[step] == item2:
count = count + 1
d_output_array[step] = count
if __name__ == '__main__':
import timeit
# make_multithread(benchmark, 64)
print(timeit.timeit("benchmark()", setup="from __main__ import benchmark", number=1))
如果安装了 python 3.7、Numba 和 codatoolkit,则可以 运行 重现上面的代码。我在 Linux Mint 20。
我有 32 个内核 - 一个 100% 占用而其他人都闲着似乎不太对。
我想知道为什么会这样,是否有办法让其他内核帮助提高性能?
我如何调查是什么占用了 100% 的单核并了解发生了什么?
从主机线程的角度来看,CUDA 内核启动(和一些其他操作)是异步。正如您所说,您是 运行 GPU 工作的计算密集型部分。
因此主机线程除了启动一些工作并等待它完成外,无事可做。这里的等待过程是一个 spin-wait 这意味着 CPU 线程处于紧密循环中,等待状态条件改变。
CPU 线程将在此处触发自旋等待:
out = d_output_array.copy_to_host()
这是内核启动后的代码行,它期望将(有效的)结果从 GPU 复制回 CPU。为了使其工作,CPU 线程必须在那里等待,直到结果准备就绪。 Numba 在 GPU 和 CPU activity 之间通过 阻塞 同步操作实现了这一点。因此,在程序的大部分时间里,CPU 线程实际上在该行代码处等待。
此等待占用该线程的 100% activity,因此一个核心被视为已充分利用。
没有任何意义或理由尝试将此“工作”“分发”给多个 threads/cores,因此这不是您建议的“性能”问题。
任何显示热点或使用 PC 采样的 CPU 分析器都应该能够为您提供这方面的图片。该行代码应该显示在您的 CPU/core/thread.
最常访问的代码行列表的顶部附近