我有大约40k行,我想在这些行上测试各种选择组合。我所说的选择是指布尔掩码。掩模/滤镜的数量约为250 is。
当前简化的代码如下:
np_arr = np.random.randint(1, 40000, 40000)
results = np.empty(250000000)
filters = np.random.randint(1, size=(250000000, 40000))
for i in range(250000000):
row_selection = np_arr[filters[i].astype(np.bool_)] # Select rows based on next filter
# Performing simple calculations such as sum, prod, count on selected rows and saving to result
results[i] = row_selection.sum() # Save simple calculation result to results array
我尝试了Numba和Multiprocessing,但由于大多数处理都是在过滤器选择中,而不是计算中,这没有太大帮助。
解决这个问题最有效的方法是什么?有没有办法将其并行化?就我所见,我需要遍历每个过滤器,然后分别计算sum,prod,count等,因为我不能并行应用过滤器(即使应用过滤器后的计算非常简单)。
感谢您在性能改进/加速方面的任何建议。
发布于 2018-11-22 17:09:26
要在Numba
中获得良好的性能,只需避免掩蔽,从而避免非常昂贵的阵列拷贝。您必须自己实现筛选器,但您提到的筛选器应该没有任何问题。
并行化也很容易做到。
示例
import numpy as np
import numba as nb
max_num = 250000 #250000000
max_num2 = 4000#40000
np_arr = np.random.randint(1, max_num2, max_num2)
filters = np.random.randint(low=0,high=2, size=(max_num, max_num2)).astype(np.bool_)
#Implement your functions like this, avoid masking
#Sum Filter
@nb.njit(fastmath=True)
def sum_filter(filter,arr):
sum=0.
for i in range(filter.shape[0]):
if filter[i]==True:
sum+=arr[i]
return sum
#Implement your functions like this, avoid masking
#Prod Filter
@nb.njit(fastmath=True)
def prod_filter(filter,arr):
prod=1.
for i in range(filter.shape[0]):
if filter[i]==True:
prod*=arr[i]
return sum
@nb.njit(parallel=True)
def main_func(np_arr,filters):
results = np.empty(filters.shape[0])
for i in nb.prange(max_num):
results[i]=sum_filter(filters[i],np_arr)
#results[i]=prod_filter(filters[i],np_arr)
return results
发布于 2018-11-22 16:40:53
改进的一种方法是将as_type移到循环之外。在我的测试中,它将执行时间减少了一半以上。为了进行比较,请检查以下两个代码:
import numpy as np
import time
max_num = 250000 #250000000
max_num2 = 4000#40000
np_arr = np.random.randint(1, max_num2, max_num2)
results = np.empty(max_num)
filters = np.random.randint(1, size=(max_num, max_num2))
start = time.time()
for i in range(max_num):
row_selection = np_arr[filters[i].astype(np.bool_)] # Select rows based on next filter
# Performing simple calculations such as sum, prod, count on selected rows and saving to result
results[i] = row_selection.sum() # Save simple calculation result to results array
end = time.time()
print(end - start)
采用2.12
而
import numpy as np
import time
max_num = 250000 #250000000
max_num2 = 4000#40000
np_arr = np.random.randint(1, max_num2, max_num2)
results = np.empty(max_num)
filters = np.random.randint(1, size=(max_num, max_num2)).astype(np.bool_)
start = time.time()
for i in range(max_num):
row_selection = np_arr[filters[i]] # Select rows based on next filter
# Performing simple calculations such as sum, prod, count on selected rows and saving to result
results[i] = row_selection.sum() # Save simple calculation result to results array
end = time.time()
print(end - start)
采用0.940
https://stackoverflow.com/questions/53434568
复制