Для моего класса параллельных вычислений мне нужно подумать и создать параллельную реализацию алгоритма сортировки выбора.Идея состоит в том, чтобы иметь возможность масштабировать его на несколько потоков, чтобы он стал быстрее, чем последовательная реализация.
Моя идея заключалась в следующем: Идея сортировки с параллельным выбором
За последние несколько дней я создал следующую реализацию, но она намного медленнее, чем последовательный алгоритм.Всякий раз, когда я использую больше потоков, это также намного медленнее, чем когда я использую один поток.Я впервые работаю с потоками, поэтому не уверен, правильно ли я это реализовал.
SelectionSort.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SelectionSort {
private static final int availableProcessors = Runtime.getRuntime().availableProcessors();
private static final int NUMBER_COUNT = 10000;
private static List<Integer> sortedList = new ArrayList<>();
private static int[][] splitArray;
private static List<Integer> lowestNumbers = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
List<Integer> numbers = Numbers.GenerateNumber(NUMBER_COUNT);
class Lowest {
synchronized int getLowest(int index) {
int lowestInArray = Integer.MAX_VALUE;
for (int i = 0; i < splitArray[index].length; i++) {
if (splitArray[index][i] < lowestInArray) {
lowestInArray = splitArray[index][i];
}
}
return lowestInArray;
}
}
Lowest lowest = new Lowest();
class SelectionSortThread extends Thread {
private int splitArrayIndex;
private SelectionSortThread(int splitArrayIndex) {
this.splitArrayIndex = splitArrayIndex;
}
public void run() {
lowestNumbers.add(lowest.getLowest(splitArrayIndex));
}
}
long startingTime = System.currentTimeMillis();
for (int i = 0; i < NUMBER_COUNT; i++) {
List<Thread> threads = new ArrayList<>();
splitArray = fillSplitArray(availableProcessors, numbers);
lowestNumbers.clear();
for (int j = 0; j < availableProcessors; j++) {
if(splitArray[j] != null) {
threads.add(new SelectionSortThread(j));
}
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
int lowestInArray = getLowest(lowestNumbers);
numbers = swap(numbers, lowestInArray);
sortedList.add(numbers.get(0));
numbers.remove(0);
}
System.out.println("Sorted list: " + Arrays.toString(sortedList.toArray()));
System.out.println(System.currentTimeMillis() - startingTime);
}
private static int getLowest(List<Integer> lowestNumbers) {
int lowestInArray = Integer.MAX_VALUE;
for (Integer lowestNumber : lowestNumbers) {
if (lowestNumber < lowestInArray) {
lowestInArray = lowestNumber;
}
}
return lowestInArray;
}
private static List<Integer> swap(List<Integer> list, int lowest)
{
int n = list.size();
for(int i = 0; i < n; i++)
{
if(list.get(i) == lowest) {
Collections.swap(list, 0, i);
return list;
}
}
return null;
}
static int[][] fillSplitArray(int arrayAmount, List<Integer> listToUse) {
if (listToUse.size() == 0) {
return new int[0][0];
}
int splitLength = (int) Math.ceil((double) listToUse.size() / (double) arrayAmount);
int[][] splits = new int[arrayAmount][];
int j = 0;
int k = 0;
for (int i = 0; i < listToUse.size(); i++) {
if (k == splitLength) {
k = 0;
j++;
}
if (splits[j] == null) {
int remainingNumbers = listToUse.size() - i;
splits[j] = new int[Math.min(remainingNumbers, splitLength)];
}
splits[j][k++] = listToUse.get(i);
}
return splits;
};
}
Numbers.java
import java.util.ArrayList;
import java.util.List;
class Numbers {
static List<Integer> GenerateNumber(int numberCount) {
List<Integer> temp = new ArrayList<>();
for (int i = numberCount; i > 0; i--) {
temp.add(i);
}
return temp;
}
}
Есть ли что-то, что я делаю совершенно неправильно или что я могу улучшить?Я ожидаю, что параллельная реализация будет быстрее, чем последовательная, но пока это не так.В настоящее время это намного медленнее.