我有23x23x30
的空格,1x1x1
的每个多维数据集代表一个点,其中一些23x23x30
点的数字来自-65 to -45
,我想要确保在填充点周围5x5x30
的任何给定区域中不应超过1个数字,如果5x5x30
的任何区域中有多个点,则应删除具有最小数字的点。我已经使用嵌套的for
循环以串行方式完成了这个操作,但这是非常昂贵的操作。我想并行化这个操作。我有n
个核心,每个核心都有自己的23x23x30
总区域的子区域,没有任何重叠。我可以收集这些“子区域”并构建上面提到的23x23x30
的完整区域,这样所有核心都可以在它们的“子区域”同时访问23x23x30
的完整区域好。我不确定在python中是否有任何可用于此类操作的库。在我的应用程序中,8个进程将填充此23x23x30
空间大约3500
个点,现在我正在对所有8个进程执行此“过滤”操作(即复制工作)这是浪费资源,所以我必须并行执行“过滤”,以便有效地使用可用资源。
以下是序列码:self.tntatv_stdp_ids
是一个字典,其中包含键step1
,step2
....最多30
个维度步骤z
。此键具有填充该步骤中的点的数字(1 to 529
)。请注意,在代码的串行实现中,z
维度中每个步骤中的点都来自1 to 529
。
self.cell_voltages
是一个字典,其中包含键step1
,step2
....最多30
个维度,z
。每个键给出一个点中出现的数字。
a_keys = self.tntatv_stdp_ids.keys()
#Filter tentative neuron ids using suppression algo to come up with final stdp neuron ids.
for i in range(0,len(a_keys)):
b_keys= list(set(a_keys) - set([a_keys[i]]))
c_keys = self.tntatv_stdp_ids[a_keys[i]]
for j in range(0,len(b_keys)):
d_keys=self.tntatv_stdp_ids[b_keys[j]]
for k in c_keys[:]:
key = k
key_row= key/(image_size-kernel+1)
key_col = key%(image_size-kernel+1)
remove =0
for l in d_keys[:]:
target = l
tar_row = target/(image_size-kernel+1)
tar_col = target%(image_size-kernel+1)
if(abs(key_row-tar_row) > kernel-1 and abs(key_col-tar_col) > kernel-1):
pass
else:
if(self.cell_voltages[a_keys[i]][key]>=self.cell_voltages[b_keys[j]][target]):
d_keys.remove(target)
else:
remove+=1
if(remove):
c_keys.remove(key)
在此操作结束时,如果30
23x23x1
个30
区域内还有多个积分,则23x23x1
23x23x1
个区域中的每一个都有一个最终赢家点可以通过查看30
点的剩余填充点中哪一个具有最高编号来选择。通过这种方式,获胜者的最大数量可以是23x23x30
中所有点的23x23x1
,30
中的每一个都是1。也可能少于23x23x30
,取决于填充的for (const p in smaller)
smaller[p] = larger[p];
点的数量。
答案 0 :(得分:1)
此问题可能不需要并行化:
# Generate a random array of appropriate size for testing
super_array = [[[None for _ in range(30)] for _ in range(529)] for _ in range(529)]
for _ in range(3500):
super_array[random.randint(0, 528)][random.randint(0, 528)][random.randint(0,29)] = random.randint(-65, -45)
第一步是构建一个填充节点列表:
filled = []
for x in range(len(super_array)):
for y in range(len(super_array[0])):
for z in range(len(super_array[0][0])):
if super_array[x][y][z] is not None:
filled.append((x, y, z, super_array[x][y][z]))
然后,从高到低排序列表:
sfill = sorted(filled, key=lambda x: x[3], reverse=True)
现在,生成一个阻塞网格:
block_array = [[None for _ in range(529)] for _ in range(529)]
遍历列表,在找到节点并删除已占用社区中的节点时阻止邻居:
for node in sfill:
x, y, z, _ = node
if block_array[x][y] is not None:
super_array[x][y][z] = None # kill node if it's in the neighborhood of a larger node
else: # Block their neighborhood
for dx in range(5):
for dy in range(5):
cx = x + dx - 2
cy = y + dy - 2
if 529 > cx >= 0 and 529 > cy >= 0:
block_array[cx][cy] = True
一些注意事项:
这使用滑动邻域,因此它会检查每个节点上居中的5x5。从最高到最低进行检查非常重要,因为这样可以确保删除的节点以前不会强制删除其他节点。
您可以通过执行范围而不是完整的529x529数组来更有效地执行此操作,但是邻居阻塞只需不到一秒钟,从生成的数组到修剪的最终列表的完整过程是1.2秒。
只需在任何z
堆栈中添加最高值节点,即可构建已填充节点列表。这将减少列表的大小,如果大量节点以相同的x,y值结束,则必须对其进行排序。
在23x23x30上,它需要大约18ms,再次包括构建3d阵列的时间:
timeit.timeit(prune_test, number=1000)
17.61786985397339