Для реализации MCMC я хочу вычислить тензор ковариации C в единицах.
Рабочий однопоточный код
Расстояние между двумя элементами основано на расстоянии между их индексами.Для справки, вот рабочий однопоточный код (с примером расстояния):
import numpy as np
#set size, dimensions, etc
size = 20
ndim = 2
shape = (size,)*ndim*2
#initialize tensor
C = np.zeros(shape)
#example distance
dist = lambda x, y: np.sqrt(np.sum((x-y)**2))
#this runs as a class method, so please forgive my sloppy coding here
def update_tensor():
it = np.nditer(C, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = np.array(it.multi_index)
it[0] = dist(idx[:idx.shape[0]//2], idx[idx.shape[0]//2:])
it.iternext()
update_tensor()
Попытка решения
Теперь проблема в том, что при применении C к матрице x является многопоточнымОперация:
x = np.random.standard_normal((size,)*ndim)
result = np.tensordot(C, x, axes=ndim)
, не суммирующая записи C не является.Моя идея состояла в том, чтобы разделить C после инициализации вдоль его первой оси и выполнить итерацию по частям отдельно:
import multiprocessing
def _calc_distances(C):
'Calculate distances of submatrices'
it = np.nditer(C, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = np.array(it.multi_index)
it[0] = dist(idx[:idx.shape[0]//2], idx[idx.shape[0]//2:])
it.iternext()
return C
def update_tensor(C):
'Updates Covariance Operator'
#Multicore Processing
n_processes = multiprocessing.cpu_count()
Chunks = [
C[i*C.shape[0]//n_processes:(i+1)*C.shape[0]//n_processes] for i in range(0, n_processes-1)
]
Chunks.append(C[C.shape[0]//n_processes*(n_processes-1):])
with multiprocessing.Pool(n_processes+1) as p:
#map and stitch together
C = np.concatenate(
p.map(_calc_distances, Chunks)
)
Но это не удается, поскольку изменяются значения подматриц.
Вопрос
Есть ли лучшее решение для этого?Как мне исправить проблему с индексом?Вероятно, самый лучший способ - это просто перебирать части массива с потоками, разделяющими данные C. Это возможно?
Q / A
Q: Вам нужно использовать numpy?итератор?A: Нет, это хорошо, но я могу отказаться от этого.