[Мета: Этот вопрос давил на меня из-за того, что так долго оставался без ответа. Я лично уклонялся от этого из-за использования фразы «самый эффективный с точки зрения вычислений». На практике трудно гарантировать, что какое-либо решение соответствует этому описанию с учетом вариаций, которые могут происходить от одной целевой машины или набора данных к другой. Но поскольку никто больше не выступил, я сделаю несколько комментариев в надежде, что они могут быть полезны.]
Несколько вещей, которые выделяются для меня в вашем коде:
1) Если я чего-то не упускаю, вы будете многократно, очень много раз за время вычисления вычислять norm(V[r, ..])
избыточно. Асимптотически это говорит о том, что вы выполняете квадратичную работу там, где требуется только линейная работа. Я бы предложил вычислить норму для каждой строки один раз и сохранить ее в массиве, чтобы избежать этого избыточного вычисления:
var normVrow: [docs] real = [r in docs] norm(V[r,..]);
Затем во внутреннем цикле вы можете просто обратиться к normVrow[i]
или normVrow[j]
.
2) Поскольку это Chapel, и ваш цикл, похоже, не имеет взаимозависимостей между циклами, вместо использования последовательных for
циклов, вам, вероятно, следует использовать параллельный forall
цикл для этого вычисления. Возникает вопрос:
(а) измените внешний цикл на forall
(что приведет к дисбалансу нагрузки, поскольку общее пространство итераций имеет треугольную форму),
(b) изменить оба цикла на forall
циклов (что помогло бы решить проблему дисбаланса нагрузки за счет чрезмерной декомпозиции, но, вероятно, также увеличило бы накладные расходы), или
(c) превратить внешний цикл в динамически планируемый цикл для устранения дисбаланса нагрузки.
Моим инстинктом было бы выбрать вариант c, используя dynamic итератор:
use DynamicIters;
forall i in dynamic(ndocs) {
...
}
3) И последнее, что следует учитывать, - это избегать треугольного пространства итераций и просто избыточно вычислять X[i,j]
и X[j,i]
, даже если они будут иметь одинаковое значение. Это может не иметь смысла при запуске с разделяемой памятью, но если вы выполняете вычисления в распределенном массиве X
, вы, вероятно, сократите обмен данными, поскольку эти значения матрицы будут храниться на разных процессорах. При таком подходе вы можете выполнять итерацию с одним forall
циклом по X.domain
, и результат будет хорошо сбалансирован по нагрузке по умолчанию без необходимости в динамическом итераторе.
person
Brad
schedule
09.12.2017