Cython nogil with ThreadPoolExecutor 不给加速



我假设如果我使用nogil指令在 Cython 中编写代码,那确实会绕过 gil,我可以使用ThreadPoolExecutor来使用多个内核。或者,更有可能的是,我在实现中搞砸了一些东西,但我似乎无法弄清楚是什么。

我已经使用 Barnes-Hut 算法编写了一个简单的 n 体模拟,并希望并行进行查找:

# cython: boundscheck=False
# cython: wraparound=False
...
def estimate_forces(self, query_point):
...
cdef np.float64_t[:, :] forces
forces = np.zeros_like(query_point, dtype=np.float64)
estimate_forces_multiple(self.root, query_point.data, forces, self.theta)
return np.array(forces, dtype=np.float64)

cdef void estimate_forces_multiple(...) nogil:
for i in range(len(query_points)):
...
estimate_forces(cell, query_point, forces, theta)

我像这样调用代码:

data = np.random.uniform(0, 100, (1000000, 2))
executor = ThreadPoolExecutor(max_workers=max_workers)
quad_tree = QuadTree(data)
chunks = np.array_split(data, max_workers)
forces = executor.map(quad_tree.estimate_forces, chunks)
forces = np.vstack(list(forces))

我省略了很多代码,以使有问题的代码更清晰。我的理解是,增加max_workers应该使用多个内核并提供实质性的加速,但是,情况似乎并非如此:

> time python barnes_hut.py --max-workers 1
python barnes_hut.py  9.35s user 0.61s system 106% cpu 9.332 total
> time python barnes_hut.py --max-workers 2
python barnes_hut.py  9.05s user 0.64s system 107% cpu 9.048 total
> time python barnes_hut.py --max-workers 4
python barnes_hut.py  9.08s user 0.64s system 107% cpu 9.035 total
> time python barnes_hut.py --max-workers 8
python barnes_hut.py  9.12s user 0.71s system 108% cpu 9.098 total

构建四叉树需要不到 1 秒的时间,因此大部分时间都花在estimate_forces_multiple上,但显然,使用多个线程无法获得任何速度。从top来看,它似乎也没有使用多个内核。

我的猜测是,我一定错过了一些非常关键的东西,但我真的想不通是什么。

我错过了一个实际上发出释放 GIL 信号的关键部分:

def estimate_forces(self, query_point):
...
cdef np.float64_t[:, :] forces
forces = np.zeros_like(query_point, dtype=np.float64)
# HERE
cdef DTYPE_t[:, :] query_points = query_point.data
with nogil:
estimate_forces_multiple(self.root, query_points, forces, self.theta)
return np.array(forces, dtype=np.float64)

我还发现 UNIXtime命令不能为多线程程序执行我想要的操作,并且报告了相同的数字(我猜它报告了 CPU 时间?使用 pythontimeit提供了预期的结果:

max_workers=1: 91.2366s
max_workers=2: 36.7975s
max_workers=4: 30.1390s
max_workers=8: 24.0240s

最新更新