首页 > 解决方案 > 种族条件?- 多线程结果不同于单线程

问题描述

我正在研究一种并行 Cython 算法,该算法利用“prange”函数进行并行化。基本上,我有一个并行更新的 numpy 内存视图。我注意到由于值与单线程结果不同,因此存在竞争条件或正在发生的事情。有没有人有什么方向可以告诉我在哪里看?

我试图调整“prange”参数,但似乎并没有解决问题。我对 C 的理解相当有限,但我确实读过它,发现循环中的变量都是私有的,因为它们应该是私有的。

mp 和 mpi 是内存视图。

for diag in prange(minlag, profile_len, num_threads=n_jobs, nogil=True):
        c = 0
        for i in range(diag, diag + w):
            c = c + ((ts[i] - mu[diag]) * (ts[i-diag] - mu[0]))

        for offset in range(n - w - diag + 1):
            c = c + df[offset] * dg[offset + diag] + df[offset + diag] * dg[offset]
            c_cmp = c * sig[offset] * sig[offset + diag]

            # update the distance profile and profile index
            if c_cmp > mp[offset]:
                if c_cmp > 1:
                    c_cmp = 1
                mp[offset] = c_cmp
                mpi[offset] = offset + diag

            if c_cmp > mp[offset + diag]:
                if c_cmp > 1:
                    c_cmp = 1
                mp[offset + diag] = c_cmp
                mpi[offset + diag] = offset

单线程和多线程的 mp 和 mpi 值应该相同。现在情况并非如此。

标签: pythonparallel-processingcython

解决方案


for offset in range(n - w - diag + 1):
      # ... some stuff ...
            mp[offset] = c_cmp
            mpi[offset] = offset + diag
      # ... some stuff ...
            mp[offset + diag] = c_cmp
            mpi[offset + diag] = offset

对某个数字的一​​系列偏移量的分配mpmpi运行0(我们不知道,因为它是一个不完整的示例,但这并不特别重要)。这发生在每个线程中。

由于您的算法似乎可以在循环中更新和在同一循环中mp使用mp,因此对我来说似乎不是特别可并行化。(可以改为并行化内部 ( offset) 循环,但我认为这会导致...[offset + diag]线路出现问题。)


本质上,如果您将循环与索引并行化,diag那么您应该在循环中更改的唯一内容是:

  1. 单个值作为“减少变量” ( +-*/)

  2. diag 使用且仅diag索引的数组。

其他事情有时是可能的,但您必须完全了解自己在做什么,并向自己证明多个线程不会写入相同的数据。


推荐阅读