2016-03-24 2 views
0

Я планировал использовать параллелизм в проекте, узнав, что он действительно увеличился через множество для многих. Теперь я не много работал над многопоточными или параллельными процессами, поэтому решил изучить и иметь простое доказательство концепции, прежде чем использовать его в реальном проекте.
Ниже приведены два примера, я пытался:Когда параллелизм/многопоточность помогают повысить производительность?

1. With use of concurrency 

    public static void main(String[] args) 

    { 
     System.out.println("start main "); 

     ExecutorService es = Executors.newFixedThreadPool(3); 
     long startTime = new Date().getTime(); 
     Collection<SomeComputation> collection = new ArrayList<SomeComputation>(); 
     for(int i=0; i< 10000; i++){ 
      collection.add(new SomeComputation("SomeComputation"+i)); 
     } 
     try { 
      List<Future<Boolean>> list = es.invokeAll(collection); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("\n end main "+(new Date().getTime() - startTime)); 
    } 

2. Without use of concurrency 

     public static void main(String[] args) { 

      System.out.println("start main "); 
      long startTime = new Date().getTime(); 
      Collection<SomeComputation> collection = new ArrayList<SomeComputation>(); 
      for(int i=0; i< 10000; i++){ 
      collection.add(new SomeComputation("SomeComputation"+i)); 
     } 
     for(SomeComputation sc:collection) 
     { 
     sc.compute(); 
     } 
     System.out.println("\n end main "+(new Date().getTime() - startTime)); 
     } 

    Both share a common class 

     class SomeComputation implements Callable<Boolean> 
     { 
      String name; 
      SomeComputation(String name){this.name=name;} 
      public Boolean compute() 
      { 
       someDumbStuff(); 
       return true; 
      } 

      public Boolean call() 
      { 
       someDumbStuff(); 
       return true; 
      } 

      private void someDumbStuff() 
      { 
       for (int i = 0;i<50000;i++) 
       { 
        Integer.compare(i,i+1); 
       } 
       System.out.print("\n done with "+this.name); 
      } 
     } 

Теперь анализ после 20 нечетных пробегов каждого подхода.
Первый с параллелизмом занимает в среднем 451 мсек.
Второй без параллелизма занимает в среднем 290 мс.
Теперь я узнал, что это зависит от конфигурации, ОС, версии (java 7) и процессора. Но все было одинаково для обоих подходов. Также узнал, что стоимость параллелизма является доступной, когда вычисление тяжелое. Но этот момент мне не был понятен.
Надеюсь, что кто-то может помочь мне понять это больше.
PS: Я пробовал найти похожие вопросы, но мог бы найти этот вид. Пожалуйста, прокомментируйте ссылку, если вы это сделаете.

+0

Покойный Джин Амдал провел некоторые исследования, которые могут вам помочь; см. также [закон Амдаля] (https://en.wikipedia.org/wiki/Amdahl's_law). –

+0

Спасибо @ElliottFrisch. Я собираюсь прочитать его прямо сейчас. –

+0

Попробуйте увеличить продолжительность цикла в 'someDumbStuff' примерно до 1000000, и вы можете начать видеть более ожидаемый тренд. – flakes

ответ

1

Параллельность имеет как минимум две разные цели: 1) производительность и 2) простоту кода (например, 1000 слушателей для веб-запросов).

Если ваша цель - производительность, вы не можете получить больше ускорения, чем количество аппаратных ядер, которые вы положили на работу. (И только в том случае, если потоки связаны с ЦП). Кроме того, каждый поток имеет значительные накладные расходы на запуск. Итак, если вы запускаете 1000 потоков на 4-ядерном компьютере, вы не сможете сделать ничего лучше, чем 4-кратное ускорение, но против этого у вас есть 1000 затрат на запуск потока.

+0

Спасибо за ответ .. Моя цель - производительность. Не уверен, что потоки связаны с ЦП. Означает ли это, что данный ограниченный параллельный параллельный компьютер не поможет? Потому что, если я увеличиваю количество потоков, чтобы сказать в _newFixedThreadPool_, время уменьшается .. но ваш ответ по-прежнему полезен. –

+0

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

1

concurrecy необходима, когда потоки обмена одни и те же источники данных поэтому, когда какой-то поток работает с этим источником остальные должны ждать, пока он не закончить работу, чем они имеют Acces поэтому вам нужно научиться синхронизированный METHODE и bluck или некоторые вещи, как, что простите за мой английский читать это Turial полезно https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

1

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

Кроме этого, одновременно программа добавляет к производительности, только если его возможность сохранить циклы CPU для вас, то есть цель состоит в том, чтобы держать процессор или процессоры все время занят и не тратить свои циклы, которые Кроме того, это означает, что вы позволяете вашему CPU делать что-то полезное, когда ваша программа должна быть занята в чем-то неинтегрированным заданием, например, при ожидании ввода/вывода на диск, Wait for Locks, Sleeping, GUI app user wait и т. д. - эти времена просто добавляют время общее время выполнения программы.

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

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

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

На мой взгляд, хорошие кандидаты на параллелизм являются длинные бегущие задачи с участием одного из ожидания операций, упомянутых выше в противном случае вы не видите много gain.Programs, которые нуждаются в некоторых фоновых задач также являются хорошими кандидатами на параллелизм.

Параллелизм не следует путать с многозадачностью процессора, то есть при одновременном запуске разных программ на одном процессоре.

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

+0

это было действительно полезно, спасибо. –

Смежные вопросы