嗯 - 我不知道你是否可以'向量化'該代碼,以便它可以在本機代碼而不是Python中運行。加速numpy和scipy的訣竅總是能夠實現這一點。
如果你可以在1GHz的CPU中使用本機代碼運行該代碼,並使用1 FP指令作爲時鐘,那麼你可以在10小時內完成它。 (5000 * 2 * 30000 * 120000)/ 1024 ** 3
將其提升至1.5Ghz x 2個CPU物理內核x 4路SIMD指令,帶乘法+積分(Intel AVX擴展,大多數CPU都可用)和您可以將這個數字嘎吱嘎吱地下到一個小時,在一個適中的核心i5機器上以2 x 100%的速度運行。但是,這需要在本地代碼中進行完全SIMD優化 - 這遠非一項微不足道的任務(儘管如果你決定走這條道路,那麼關於SO的進一步問題可以得到人們的幫助,或者用SIMD編碼弄溼他們的手:-)) - 接口這個代碼在C中與Scipy並不是很難用cython,例如(你只需要那部分就可以把它變成10個小時以上的數字)
現在...至於算法優化和保持Python的東西:-)
事實是,你不需要完全計算全部距離A行的距離 - 你只需要保留一個排序的5行較低的列表 - 任何時候累加的平方和大於第5個最近的行(到目前爲止),您只需中止該行的計算。
你可以使用Python的heapq操作爲:
import heapq
import math
def get_closer_rows(b_row, a):
result = [(float("+inf"), None) * 5]
for i, a_row in enumerate(a):
distance_sq = 0
count = 0
for element_a, element_b in zip(a_row, b_row):
distance_sq += element_a * element_b
if not count % 64 and distance_sq > result[4][0]:
break
count += 1
else:
heapq.heappush(result, (distance, i))
result[:] = result[:5]
return [math.sqrt(r) for r in result]
closer_rows_to_b = []
for row in b:
closer_rows_to_b.append(get_closer_rows(row, a))
注意附配‘計數’,以避免價值昂貴的檢索和對比所有的乘法。 現在,如果您可以使用pypy而不是常規Python來運行此代碼,我相信它可以充分利用JITting,並且如果您在純Python中運行代碼(例如:non numpy/scipy向量化代碼)。