227 lines
9.5 KiB
Java
227 lines
9.5 KiB
Java
import java.util.Random;
|
|
import java.util.concurrent.*;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
public class MinDivisionTask {
|
|
static double[][] mainArray = new double[4000][4000];
|
|
static double[][] bufferArray = new double[mainArray.length][mainArray.length];
|
|
static final int FRONTIER = 5000; // Порог разбиения
|
|
static final int THREADS = 2; // Кол-во потоков
|
|
static int countOftests = 20; // Кол-во тестов
|
|
|
|
public static void main(String[] args) {
|
|
DoTests();
|
|
}
|
|
public static void DoTests() {
|
|
long SingleThreadedTimeSum = 0;
|
|
long ThreadPoolExecutorTimeSum = 0;
|
|
long ForkJoinPoolTimeSum = 0;
|
|
int count = 0;
|
|
Random random = new Random();
|
|
while (count != countOftests) {
|
|
count += 1;
|
|
for (int i = 0; i < mainArray.length; i++) {
|
|
for (int j = 0; j < mainArray.length; j++) {
|
|
mainArray[i][j] = random.nextInt(-100,100);
|
|
bufferArray[i][j] = mainArray[i][j];
|
|
}
|
|
}
|
|
//PrintLogMatrix(mainArray); System.out.println();
|
|
|
|
// Однопоточный алгоритм
|
|
long SingleThreadedTime = ComputeAndPrintDuration("SingleThreadedAlgorithm");
|
|
SingleThreadedTimeSum += SingleThreadedTime;
|
|
// Многопоточный алгоритм
|
|
long ThreadPoolExecutorTime = ComputeAndPrintDuration("ThreadPoolExecutorAlgorithm");
|
|
ThreadPoolExecutorTimeSum += ThreadPoolExecutorTime;
|
|
// ForkJoinPool-алгоритм
|
|
long ForkJoinPoolTime = ComputeAndPrintDuration("ForkJoinPoolAlgorithm");
|
|
ForkJoinPoolTimeSum += ForkJoinPoolTime;
|
|
|
|
System.out.println("{Тест "+ count + "} " + "SingleThreadedTime: " + SingleThreadedTime +
|
|
" ThreadPoolExecutorTime: " + ThreadPoolExecutorTime + " ForkJoinPoolTime: " + ForkJoinPoolTime);
|
|
}
|
|
System.out.println("SingleThreadedTime: " + SingleThreadedTimeSum/countOftests);
|
|
System.out.println("ThreadPoolExecutorTime: " + ThreadPoolExecutorTimeSum/countOftests);
|
|
System.out.println("ForkJoinPoolTime: " + ForkJoinPoolTimeSum/countOftests);
|
|
}
|
|
public static void CopyArray() {
|
|
for (int i = 0; i < mainArray.length; i++) {
|
|
for (int j = 0; j < mainArray.length; j++) mainArray[i][j] = bufferArray[i][j];
|
|
}
|
|
}
|
|
public static void PrintLogMatrix(double[][] mainArray) {
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
System.out.print(mainArray[i][j] + " ");
|
|
}
|
|
System.out.println();
|
|
}
|
|
}
|
|
public static long ComputeAndPrintDuration(String typeOfAlgoritm) {
|
|
long startTime = 0, endTime = 0, duration;
|
|
switch (typeOfAlgoritm) {
|
|
case "SingleThreadedAlgorithm":
|
|
startTime = System.nanoTime();
|
|
SingleThreadedAlgorithm(mainArray);
|
|
endTime = System.nanoTime();
|
|
break;
|
|
case "ThreadPoolExecutorAlgorithm":
|
|
startTime = System.nanoTime();
|
|
ThreadPoolExecutorAlgorithm(mainArray);
|
|
endTime = System.nanoTime();
|
|
break;
|
|
case "ForkJoinPoolAlgorithm":
|
|
startTime = System.nanoTime();
|
|
ForkJoinPoolAlgorithm(mainArray);
|
|
endTime = System.nanoTime();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
duration = (endTime - startTime) / 1000000;
|
|
//System.out.println("Время выполнения: " + (duration) + " мс\n");
|
|
CopyArray();
|
|
return duration;
|
|
}
|
|
|
|
public static void SingleThreadedAlgorithm(double[][] mainArray) {
|
|
//System.out.println("Однопоточный алгоритм");
|
|
double min = Double.MAX_VALUE;
|
|
for (int i = 0; i < mainArray.length; i++) {
|
|
for (int j = 0; j < mainArray.length; j++) {
|
|
if(min > mainArray[i][j]) min = mainArray[i][j];
|
|
}
|
|
}
|
|
//System.out.println("Наименьший элемент: " + min);
|
|
|
|
for (int i = 0; i < mainArray.length; i++) {
|
|
for (int j = 0; j < mainArray.length; j++) {
|
|
mainArray[i][j] = mainArray[i][j] / min;
|
|
}
|
|
}
|
|
|
|
//PrintLogMatrix(mainArray);
|
|
}
|
|
public static void ThreadPoolExecutorAlgorithm(double[][] mainArray) {
|
|
//System.out.println("ThreadPoolExecutorAlgorithm");
|
|
int size = mainArray.length;
|
|
ExecutorService executor = Executors.newFixedThreadPool(THREADS); // Создаем пул потоков
|
|
|
|
AtomicLong globalMin = new AtomicLong(Long.MAX_VALUE);
|
|
|
|
// Вычисление суммы элементов массива
|
|
for (int t = 0; t < THREADS; t++) {
|
|
final int startRow = t * (size / THREADS); // Начало данного потока
|
|
final int endRow = (t == THREADS - 1) ? size : (t + 1) * (size / THREADS); // Конец данного потока
|
|
|
|
executor.submit(() -> {
|
|
double localMin = Double.MAX_VALUE;
|
|
// Вычисление суммы в рамках выделенного потоку диапазона строк
|
|
for (int i = startRow; i < endRow; i++) {
|
|
for (int j = 0; j < size; j++) {
|
|
if(localMin > mainArray[i][j]) localMin = mainArray[i][j];
|
|
}
|
|
}
|
|
// Вычисление наименьшего элемента глобально
|
|
long finalLocalMin = (long)localMin;
|
|
globalMin.updateAndGet(v -> Math.min(v, finalLocalMin));
|
|
});
|
|
}
|
|
|
|
// Деление элементов массива на наименьшее значение
|
|
for (int t = 0; t < THREADS; t++) {
|
|
final int startRow = t * (size / THREADS); // Начало данного потока
|
|
final int endRow = (t == THREADS - 1) ? size : (t + 1) * (size / THREADS); // Конец данного потока
|
|
|
|
executor.submit(() -> {
|
|
for (int i = startRow; i < endRow; i++) {
|
|
for (int j = 0; j < size; j++) {
|
|
mainArray[i][j] /= globalMin.get();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
executor.shutdown();
|
|
while (!executor.isTerminated()) { /* Ожидание завершения всех задач */ }
|
|
|
|
double min = globalMin.get();
|
|
//System.out.println("Наименьший элемент: " + min);
|
|
//PrintLogMatrix(mainArray);
|
|
}
|
|
public static void ForkJoinPoolAlgorithm(double[][] mainArray) {
|
|
//System.out.println("ForkJoinPoolAlgorithm");
|
|
int size = mainArray.length;
|
|
ForkJoinPool forkJoinPool = new ForkJoinPool();
|
|
|
|
// Вычисление наименьшего элемента
|
|
MinTask minTask = new MinTask(mainArray, 0, size);
|
|
double min = forkJoinPool.invoke(minTask);
|
|
//System.out.println("Наименьший элемент: " + min);
|
|
// Деление массива на наименьший элемент
|
|
forkJoinPool.invoke(new DivisionTask(mainArray, 0, size, min));
|
|
|
|
forkJoinPool.shutdown();
|
|
//PrintLogMatrix(mainArray);
|
|
}
|
|
|
|
static class MinTask extends RecursiveTask<Double> {
|
|
private final double[][] mainArray;
|
|
private final int startRow, endRow;
|
|
|
|
MinTask(double[][] mainArray, int startRow, int endRow) {
|
|
this.mainArray = mainArray;
|
|
this.startRow = startRow;
|
|
this.endRow = endRow;
|
|
}
|
|
|
|
@Override
|
|
protected Double compute() {
|
|
if (endRow - startRow <= FRONTIER) {
|
|
double min = Double.MAX_VALUE;
|
|
for (int i = startRow; i < endRow; i++) {
|
|
for (int j = 0; j < mainArray[i].length; j++) {
|
|
if(min > mainArray[i][j]) min = mainArray[i][j];
|
|
}
|
|
}
|
|
return (Double) min;
|
|
} else {
|
|
int midRow = (startRow + endRow) / 2;
|
|
|
|
MinTask top = new MinTask(mainArray, startRow, midRow);
|
|
MinTask bottom = new MinTask(mainArray, midRow, endRow);
|
|
|
|
top.fork();
|
|
double bottomResult = bottom.compute();
|
|
return (Double) Math.min(top.join(), (long)bottomResult);
|
|
}
|
|
}
|
|
}
|
|
static class DivisionTask extends RecursiveAction {
|
|
private final double[][] mainArray;
|
|
private final int startRow, endRow;
|
|
private final double min;
|
|
|
|
DivisionTask(double[][] mainArray, int startRow, int endRow, double min) {
|
|
this.mainArray = mainArray;
|
|
this.startRow = startRow;
|
|
this.endRow = endRow;
|
|
this.min = min;
|
|
}
|
|
|
|
@Override
|
|
protected void compute() {
|
|
if (endRow - startRow <= FRONTIER) {
|
|
for (int i = startRow; i < endRow; i++) {
|
|
for (int j = 0; j < mainArray[i].length; j++) {
|
|
mainArray[i][j] /= min;
|
|
}
|
|
}
|
|
} else {
|
|
int midRow = (startRow + endRow) / 2;
|
|
invokeAll(new DivisionTask(mainArray, startRow, midRow, min),
|
|
new DivisionTask(mainArray, midRow, endRow, min));
|
|
}
|
|
}
|
|
}
|
|
} |