Многопоточные методы вычисления итеративного решателя (итерации Якоби) на ЦПJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Многопоточные методы вычисления итеративного решателя (итерации Якоби) на ЦП

Сообщение Anonymous »

Я пытаюсь реализовать многопоточную реализацию решателя jacobi. Я попробовал два разных метода с одинаковой скоростью.
Мой вопрос
  • Есть ли лучший способ сделать это ?

    ДА: Что бы это было?
  • НЕТ: Какой из моих методов — C?

Контекст
Я использую это для моделирования жидкости.< /p>
Матрица двумерная, и вы можете получить x и y, используя эту формулу:
int x = pos % xLength;
int y = pos / xLength;

Размеры матрицы составляют около 720x1280 ячеек.
Однопоточный базовый метод
< pre class="lang-java Prettyprint-override"> int size = x.length;

if (b.length != size)
throw new IllegalArgumentException("both matrix must be the same size");

// Values of x_{i-1,j}, x_{i+1,j}, x_{i,j-1}, x_{i,j+1}
double xL, xR, xB, xT, valX, valXNew;
int xLPos, xRPos, xBPos, xTPos; // Positions of x_{i-1,j}, x_{i+1,j}, x_{i,j-1}, x_{i,j+1}
double cellDiff; // The % of difference between two iterations of this cell
double curentDiff = 1d; // The current % minimal between two iterations
double[] x_new = this.matrixArrayPool.borrowObject();

for (int iter = 0; iter < SimulationConstants.MAX_JACOBI_ITERATIONS; iter++) {
curentDiff = 1;

for (int pos = 0; pos < size; pos++) {
// Get the pos of x_{i-1,j}, x_{i+1,j}, x_{i,j-1}, x_{i,j+1}

xLPos = getPosAtOffset(pos, xLength, yLength, -1, 0); // x_{i-1,j}
xRPos = getPosAtOffset(pos, xLength, yLength, 1, 0); // x_{i+1,j}
xBPos = getPosAtOffset(pos, xLength, yLength, 0, -1); // x_{i,j-1}
xTPos = getPosAtOffset(pos, xLength, yLength, 0, 1); // x_{i,j+1}

xL = x[xLPos]; // x_{i-1,j}
xR = x[xRPos]; // x_{i+1,j}
xB = x[xBPos]; // x_{i,j-1}
xT = x[xTPos]; // x_{i,j+1}

// Find the new value of x_{i,j}
valXNew = x_new[pos] = (xL + xR + xB + xT + alpha * b[pos]) * rBeta;

// Find the new % of difference

valX = x[pos];

if (valX == valXNew) continue;
cellDiff = (valXNew - valX) / valX;

if (cellDiff < 0) {
cellDiff = -cellDiff;
}

curentDiff = Math.min(cellDiff, curentDiff);
}

// Switch both matrix
System.arraycopy(x_new, 0, x, 0, size);

// Check if the current diff is lower than the threshold
if (curentDiff < SimulationConstants.MAX_JACOBI_DIFF) break;
}

Попытки многопоточности
Пул исполнителей фиксированной длины
Я пробовал многопоточность с использованием пула исполнителей с вызываемая
основная функция
double[] x_new = this.matrixArrayPool.borrowObject();
JacobiPartSolver.setGlobalVariables(x, xLength, yLength, alpha, rBeta, b, x_new);
double curentDiff = 1;

for (int iter = 0; iter < SimulationConstants.MAX_JACOBI_ITERATIONS; iter++) {

applyBoundaryConditions();

// Start the threads
try {
executor.invokeAll(this.jacobiSolverTasks);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Get the global differents
curentDiff = JacobiPartSolver.getCurrentDiff();

// Switch matrix
System.arraycopy(x_new, 0, x, 0, size);

if (curentDiff < SimulationConstants.MAX_JACOBI_DIFF) break;
}

jacobiSolverTasks — это список Callable, созданный с начальной и конечной позицией.
вызов функции
public Void call() {
if (!isSetuped)
throw new IllegalStateException("Global variables haven't been setuped");

double xL,
xR,
xB,
xT,
valXNew,
valX; // value of x_{i-1,j}, x_{i+1,j}, x_{i,j-1}, x_{i,j+1}
int xLPos, xRPos, xBPos, xTPos; // pos of x_{i-1,j}, x_{i+1,j}, x_{i,j-1}, x_{i,j+1}

double cellDiff;

for (int pos = start; pos < end; pos++) {,j+1}

xLPos = getPosAtOffset(pos, xLength, yLength, -1, 0); // x_{i-1,j}
xRPos = getPosAtOffset(pos, xLength, yLength, 1, 0); // x_{i+1,j}
xBPos = getPosAtOffset(pos, xLength, yLength, 0, -1); // x_{i,j-1}
xTPos = getPosAtOffset(pos, xLength, yLength, 0, 1); // x_{i,j+1}

xL = x[xLPos]; // x_{i-1,j}
xR = x[xRPos]; // x_{i+1,j}
xB = x[xBPos]; // x_{i,j-1}
xT = x[xTPos]; // x_{i,j+1}

valXNew = x_new[pos] = (xL + xR + xB + xT + alpha * b[pos]) * rBeta;

valX = x[pos];

if (valX == valXNew) continue;
cellDiff = (valXNew - valX) / valX;

if (cellDiff < 0) {
cellDiff = -cellDiff;
}

long cellDiffBits = Double.doubleToLongBits(cellDiff);
if (cellDiffBits < curentDiff.get()) {
curentDiff.set(cellDiffBits);
}
}

curentDiff — это AtomicLong для обеспечения безопасности потоков, поскольку это единственное значение, которое записывается несколькими потоками одновременно.
RecursiveTask с ForkJoin
Моя вторая попытка — с RecursiveTask
main function
int size = x.length;

double[] x_new = this.matrixArrayPool.borrowObject();

JacobiPartSolver.setGlobalVariables(x, xLength, yLength, alpha, rBeta, b, x_new);

double curentDiff = 1;

for (int iter = 0; iter < SimulationConstants.MAX_JACOBI_ITERATIONS; iter++) {

applyBoundaryConditions();

JacobiPartSolver jacobiSolverTask = new JacobiPartSolver(0, size);

curentDiff = forkJoinPool.invoke(jacobiSolverTask);

System.arraycopy(x_new, 0, x, 0, size);

if (curentDiff < SimulationConstants.MAX_JACOBI_DIFF) break;
}

функция вычисления и решения
@Override
public Double compute() {
if (!isSetuped)
throw new IllegalStateException("Global values not defined");

if (this.end - this.start < SUBTASK_THRESHOLD) {
return solve();
}

int mid = (this.start + this.end) / 2;
JacobiPartSolver left = new JacobiPartSolver(this.start, mid);
JacobiPartSolver right = new JacobiPartSolver(mid, this.end);

left.fork();
return Math.min(right.compute(), left.join());
}

private double solve() {
double xL,
xR,
xB,
xT,
valXNew,
valX; // Values of x_{i-1,j}, x_{i+1,j}, x_{i,j-1}, x_{i,j+1}
int xLPos, xRPos, xBPos, xTPos; // Position of x_{i-1,j}, x_{i+1,j}, x_{i,j-1}, x_{i,j+1}

double cellDiff = 1;
double minDiff = cellDiff;

for (int pos = this.start; pos < this.end; pos++) {

xLPos = getPosAtOffset(pos, xLength, yLength, -1, 0); // x_{i-1,j}
xRPos = getPosAtOffset(pos, xLength, yLength, 1, 0); // x_{i+1,j}
xBPos = getPosAtOffset(pos, xLength, yLength, 0, -1); // x_{i,j-1}
xTPos = getPosAtOffset(pos, xLength, yLength, 0, 1); // x_{i,j+1}

xL = x[xLPos]; // x_{i-1,j}
xR = x[xRPos]; // x_{i+1,j}
xB = x[xBPos]; // x_{i,j-1}
xT = x[xTPos]; // x_{i,j+1}

valXNew = x_new[pos] = (xL + xR + xB + xT + alpha * b[pos]) * rBeta;

valX = x[pos];

if (valX == valXNew) continue;
cellDiff = (valXNew - valX) / valX;

if (cellDiff < 0) {
cellDiff = -cellDiff;
}

minDiff = Math.min(minDiff, cellDiff);
}

return minDiff;
}
}


Подробнее здесь: https://stackoverflow.com/questions/782 ... rations-on
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»