Helpers - компьютеры, интернет, программирование

Одновременное слияние многих отсортированных массивов

В настоящее время я работаю над программой для одновременной сортировки строк. Моя программа принимает файл, считывает каждую строку файла в массив и разбивает массив строк на более мелкие массивы строк. Затем программа запускает по одному потоку для каждого из меньших массивов и выполняет их быструю сортировку. Как только каждый поток закончил сортировку своего массива, основной поток собирает все результаты из объектов потока. Затем предполагается объединить меньшие, теперь отсортированные массивы в один большой отсортированный массив.

В настоящее время я решил это, используя однопоточную сортировку слиянием, чтобы объединить отсортированные массивы, возвращаемые потоками быстрой сортировки. Теперь проблема с этим, поскольку слияние не происходит одновременно, сортировка в файле с использованием небольшого количества потоков (1-4) фактически делает сортировку программы максимально быстрой. Если я немного увеличу количество потоков (скажем, 15 потоков), программа на самом деле будет работать немного медленнее, чем при меньшем количестве потоков. Чтобы решить эту проблему, я хочу ввести параллелизм в мою сортировку/вложение массива слиянием.

Что я хочу сделать, так это: как только два потока закончат быструю сортировку своих частей в файле, новый поток будет вкладывать эти две части вместе, пока каждая часть в файле не будет отсортирована.

Мы очень ценим любую помощь, и я благодарен за пример кода и/или псевдокода. Заранее спасибо! :)


Текущий код для сортировки массива:

public synchronized String[] sort(){
    String[] sortedWords = new String[words.length];
    SortingThread[] sts = new SortingThread[threads];

    for(int i = 0; i < threads; i++){
        sts[i] = new SortingThread(this, splitWords[i]);
    }

    for(SortingThread st : sts){
        st.start();
    }

    for(SortingThread st : sts){
        try {
            st.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    indexes = new int[sts.length];

    for(int i = 0; i < indexes.length; i++){
        indexes[i] = 0;
    }


//This is where my merge-sorting currently starts.

    ArrayList<String> toAddTo = new ArrayList<String>();

    while(!allIndexesHaveBeenRead(sts)){
        String globalMinimum = null;
        int globalMinThread = -1;
        currentIteration: for (int i = 0; i < sts.length; i++) {
            String current;
            try{
                current = sts[i].sorted[indexes[i]];
            } catch(Exception e){
                continue currentIteration;
            }
            try{
                if(globalMinimum == null){
                    globalMinimum = current;
                    globalMinThread = i;
                }
                else if(current.compareTo(globalMinimum) < 0){
                    globalMinimum = current;
                    globalMinThread = i;
                }
            } catch (NullPointerException e){
                continue;
            }
        }
        toAddTo.add(globalMinimum);
        indexes[globalMinThread]++;
    }

    sortedWords = toAddTo.toArray(sortedWords);

    int len = 0;
    for (int i = 0; i < sortedWords.length; i++) {
        if(sortedWords[i] != null){
            len++;
        }
    }

    String[] toReturn = new String[len];

    for (int i = 0; i < toReturn.length; i++) {
        toReturn[i] = sortedWords[i];
    }

    return toReturn;
}

  • Оптимальное параллельное слияние и алгоритмы сортировки 12.05.2013
  • Вы сравнивали это с чисто последовательным алгоритмом? Разве чтение файла не является самой неэффективной частью процесса? Каков размер массива? Сколько ядер процессора у вас есть? В любом случае, если вам нужна помощь, вы должны опубликовать свой код, чтобы мы могли предложить улучшения. 12.05.2013
  • Спасибо @JBNizet. Файл, который я пытаюсь отсортировать, содержит 267000 слов. Последовательный алгоритм, вероятно, был бы лучше для файла меньшего размера, но для такого большого файла я обнаружил, что рекурсия + параллелизм — это то, что нужно. Поступают примеры кода (редактирование ОП). 12.05.2013
  • Сколько у вас ядер? Если у вас нет 16 ядер, я ожидаю, что меньшее количество потоков будет быстрее. Я предлагаю попробовать количество логических процессоров или количество ядер, которые у вас есть, так как больше, чем это, скорее всего, будет иметь больше накладных расходов, чем пользы. 12.05.2013

Ответы:


1

Сценарий вашей проблемы примерно такой

  • Основной поток требует выполнения N задач.
  • Он порождает M потоков из пула и работает над N задачами.
  • Он ждет, пока хотя бы один поток не завершит задачу и не сделает что-то с результатом.
  • Продолжает обрабатывать результаты до тех пор, пока не будут выполнены все N задач.

CompletionService в Java 5, который выполняет именно то, что требуется,

Вот решение для вашей постановки задачи,

 public class Sorter implements Callable<List<String>> {

    private List<String> data;

public Sorter(List<String> input) {
    data = input;
}

@Override
public List<String> call() throws Exception {
    Collections.sort(data);
    return data;
}

 }

И в основном классе,

  CompletionService service = new  ExecutorCompletionService(Executors.newFixedThreadPool(5));

    List<String> result = new ArrayList<String>();

    String readline = null;
    Callable<List<String>> sorter = null;
    String[] words = null;
    int noOfRunningFutures = 0;

     while ((readline = br.readLine()) != null) {
        words = readline.split(" ");
        List<String> input = Arrays.asList(words);
        sorter = new Sorter(input);

        service.submit(sorter);

        // add them to the number of futures which I am creating - to keep track of the Queue length
        noOfRunningFutures ++;
    }


    while (noOfRunningFutures > 0) 
    {
        try {

            // this is a blocking call - whenever there is a worker which is already completed
            // then it is fetched from the Queue                 
            Future<List<String>> completed = service.take();
            noOfRunningFutures --;

            // get the value from computed from the Future
            List<String> sorted =  completed.get();

            result.addAll(sorted);

            Collections.sort(result);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

Надеюсь, это поможет вам.

12.05.2013

2

Я управляю проектом разветвления TymeacDSE на SourceForge, который делает именно то, что вы ищете. Он сортирует подмножества, а затем объединяет группы подмножеств в один окончательный массив. Посмотрите здесь

13.05.2013
Новые материалы

Интуитивное понимание тензоров в машинном обучении
Тензор является важной концепцией во многих научных областях, таких как математика, физика, обработка сигналов и компьютерное зрение, и это лишь некоторые из них. В математике тензор — это..

Использование машинного обучения для диагностики болезни Альцгеймера, часть 4
Маркеры семантической согласованности для ранней диагностики болезни Альцгеймера (arXiv) Автор: Давиде Колла , Маттео Дельсанто , Марко Агосто , Бенедетто Витиелло , Даниэле Паоло Радичони..

Почему объяснимость так важна прямо сейчас?
По мере того, как системы искусственного интеллекта и инструменты на основе машинного обучения распространяются в нашей повседневной жизни, как практики, так и критики все чаще заявляют о..

Анимированный математический анализ
Использование Manim для создания математических анимированных визуализаций Визуализация данных помогает понять скрытые закономерности в данных, которые невозможно визуализировать..

Создание простого слайдера изображений с помощью JavaScript
Узнайте, как создать базовый слайдер изображений с помощью HTML, CSS и JavaScript. Введение В этом уроке мы создадим удобный слайдер изображений, используя JavaScript, HTML и CSS. Ползунок..

Создание базы данных с помощью супергероя «Python»
В этом посте мы узнаем, как создать «базу данных SQLite с помощью модуля python sqlite3, создав простую функцию входа и регистрации. Готовы ли вы к этому путешествию? Если да , давайте приступим..

ИИ для чайников: руководство для начинающих по пониманию будущего технологий
Вы чувствуете, что остались позади в мире ИИ? Не волнуйтесь, вы не одиноки! Со всей этой шумихой вокруг искусственного интеллекта может быть трудно понять, с чего начать. Но не позволяйте сленгу..