Почему ускорение параллельного программирования с использованием Executor больше, чем ядра? - PullRequest
2 голосов
/ 30 октября 2019

Я пишу программу, работающую с матричным параллельным программированием, используя платформу Executorservice. И я установил значение fixedpoolsize равным 4, однако меня удивляет то, что когда размер матрицы установлен на 5000, скорость использования многопоточности по сравнению с последовательным выполнением превышает 4 (что также является ядром моего процессора). И я проверил, что мой процессор не поддерживает гиперпоточность.

На самом деле я использую контейнер Callable and Future, поскольку моя задача многопоточности требует возврата результата.


// Part of code for parallel programming   

   double[][] x = new double[N][N];
    List<Future<double[]>> futureList = new ArrayList<>(); 
    for (int k=0;k<N;k++)
    {
        Future<double[]>temp=service.submit(new Thread.Task(N,k,matrix,vector));
        futureList.add(temp);  
    }
    for (int j = 0; j < N; j++) {
           x[j]=futureList.get(j).get(); 
    }

     public double[] call() throws Exception {
        for (int i = N - 1; i >= 0; i--)  
        {
            double sum = 0;
            for (int j = i + 1; j < N; j++)  
            {
                sum += matrix[i][j] * x[j];   
            }
            x[i] = (vector[i][k] - sum) / matrix[i][i]; 
        }
        return x;
    }

 // Part of code for Serial programming

    double[][] x = new double[N][N]; 
    for (int k=0;k<N;k++)
    {
        for (int i = N - 1; i >= 0; i--)  
        {
            double sum = 0;
            for (int j = i + 1; j < N; j++)  
            {
                sum += matrix[i][j] * x[j][k];   
            }
            x[i][k] = (vector[i][k] - sum) / matrix[i][i]; 
        }

    }

Короче, я просто убираю внутренний цикл, чтобы позволить ему запустить поток, и оставляю внешний цикл без изменений.

Нокак может быть такое ускорение?

Поскольку из моей предыдущей концепции максимальное ускорение может быть только 4. И я проверил, что задача на самом деле выполняется четырьмя потоками.

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

Это может повлиять на сродство кеша процессора. Если каждое ядро ​​работает над определенной частью проблемы, оно может повысить эффективность использования кэша. Поскольку ОЗУ до 10 и более раз медленнее, чем кеш, это может иметь ОГРОМНОЕ различие.

0 голосов
/ 30 октября 2019

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

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

ExecutorService планирует выполнение потоков и будет запускать столько параллельных потоков, сколько доступно ресурсов, включая ядра.

Вотдокументы на fixedThreadPool

public static ExecutorService newFixedThreadPool (int nThreads)

Создает пул потоков, который повторно использует фиксированное количество потоков, работающих с общим неограниченнымочередь. В любой момент не более nThreads потоков будут активными задачами обработки. Если дополнительные задачи отправляются, когда все потоки активны, они будут ждать в очереди, пока поток не станет доступным. Если какой-либо поток завершается из-за сбоя во время выполнения до завершения работы, новый будет занимать его место, если это необходимо для выполнения последующих задач. Потоки в пуле будут существовать до тех пор, пока он не будет явно отключен

Вы также можете попробовать workStealingPool

public static ExecutorService newWorkStealingPool ()

Создает пул потоков для кражи работ, используя все доступные процессоры в качестве целевого уровня параллелизма.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...