【问题标题】:Parallelizing with Cython memoryviews与 Cython 内存视图并行化
【发布时间】:2014-06-19 20:01:01
【问题描述】:

这是我正在尝试做的一个最小示例。我正在计算排列成堆叠数组的矩阵之间的成对距离。 idx 数组保存了每个子矩阵的偏移量。

当我删除parallel() 并将prange 替换为range 时,代码按预期工作(当然,只是不是并行)。

import numpy as np
cimport numpy as np
cimport cython
from cython.parallel import parallel, prange

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def all_pairs_distance(float[:,::1] stacked, int[::1] idx):
  cdef int n = idx.shape[0] - 1
  cdef float[:,::1] D = np.zeros((n,n), dtype='float32')
  cdef int i,j
  cdef float[:,::1] t1,t2
  cdef float d
  with nogil, parallel():
    for i in prange(n):
      t1 = stacked[idx[i]:idx[i+1],:]
      for j in range(i+1, n):
        t2 = stacked[idx[j]:idx[j+1],:]
        d = nogil_cython_function(t1, t2)
        D[i,j] = d
        D[j,i] = d
  return D

cdef float nogil_cython_function(float[:,::1] a, float[:,::1] b) nogil:
  # Function abbreviated for simplicity
  return 0.0

在尝试编译此文件时,每次分配给t1t2 时都会出错:

Memoryview slices can only be shared in parallel sections
  1. 我不确定如何解决此错误。这些作业不是在平行部分吗?
  2. 如何告诉编译器我的stacked memoryview 是只读的,可以在线程之间共享?

【问题讨论】:

  • 我认为你可以只给每个线程他们将实际使用的数组的一部分。检查this answer,这是使用原始指针实现的(我发现这个任务更直接)

标签: parallel-processing cython


【解决方案1】:

经过一番试验,我想通了:

for i in prange(n, nogil=True):
  for j in range(i+1, n):
    d = nogil_cython_function(stacked[idx[i]:idx[i+1],:],
                              stacked[idx[j]:idx[j+1],:])

要点是在prange 中对内存视图进行切片很好,但将这些切片分配给变量则不行。

【讨论】:

  • 这正是我需要让 prange 使用 memoryview 切片。显然其他地方没有记录是你的解决方案,只是不要将切片分配给变量,直接使用切片。
  • 或将 prange 循环内的代码“包装”成一个小辅助函数(只需重写您的 nogil_cython_function 使其接受堆叠自身而不是切片)。在辅助函数中,您可以根据需要分配内存视图。至少到目前为止,这对我来说是简单的测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多