回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p>我有很多非常大的矩阵<code>AFeatures</code>,我正在与其他一些非常大的矩阵<code>BFeatures</code>进行比较,它们的形状都是<code>(878, 2, 4, 15, 17, 512)</code>,使用欧几里德距离。我试图将这个过程并行化,以加速比较。
我在Conda环境中使用Python3,我的原始代码在100%的速度下平均使用两个CPU核:</p>
<pre><code> per_slice_comparisons = np.zeros(shape=(878, 878, 2, 4))
for i in range(878):
for j in range(878):
for k in range(2):
for l in range(4):
per_slice_comparisons[i, j, k, l] = np.linalg.norm(AFeatures[i, k, l, :] - BFeatures[j, k, l, :])
</code></pre>
<p>我尝试了两种加速代码的方法</p>
<ol>
<li><p>使用多重处理</p>
<pre><code>def fill_array(i):
comparisons = np.zeros(shape=(878, 2, 4))
for j in range(878):
for k in range(2):
for l in range(4):
comparisons[j, k, l] = np.linalg.norm(AFeatures[i, k, l, :] -BFeatures[j, k, l, :])
comparisons[j, k, l] = 0
return comparisons
pool = Pool(processes=6)
list_start_vals = range(878)
per_slice_comparisons = np.array(pool.map(fill_array, list_start_vals))
pool.close()
</code></pre>
</li>
</ol>
<p>这种方法将运行时间增加了5%左右,尽管所有8个CPU内核现在都以100%的速度使用。我已经尝试了许多不同的过程,越多,速度就越慢</p>
<ol start=“2”>
<li><p>这是一种稍微不同的方法,我使用numexpr库来执行更快的linal.norm操作。对于单个操作,此方法将运行时间减少10倍</p>
<pre><code> os.environ['NUMEXPR_MAX_THREADS'] = '8'
os.environ['NUMEXPR_NUM_THREADS'] = '4'
import numexpr as ne
def linalg_norm(a):
sq_norm = ne.evaluate('sum(a**2)')
return ne.evaluate('sqrt(sq_norm)')
per_slice_comparisons = np.zeros(shape=(878, 878, 2, 4))
for i in range(878):
for j in range(878):
for k in range(2):
for l in range(4):
per_slice_comparisons[i, j, k, l] = linalg_norm(AFeatures[i, k, l, :] - BFeatures[j, k, l, :])
</code></pre>
</li>
</ol>
<p>但是,对于嵌套for循环,这种方法将总执行时间增加了3倍。我不明白为什么简单地将这个操作放在嵌套的for循环中会显著降低性能?如果有人对如何解决这个问题有任何想法,我将非常感激</p>