Сначала и еще раз, спасибо всем, кто уже ответил на мой вопрос. Я не очень опытный программист, и это мой первый опыт работы с многопоточностью.
У меня есть пример, который работает так же, как моя проблема. Я надеюсь, что это может облегчить наше дело здесь.
public class ThreadMeasuring {
private static final int TASK_TIME = 1; //microseconds
private static class Batch implements Runnable {
CountDownLatch countDown;
public Batch(CountDownLatch countDown) {
this.countDown = countDown;
}
@Override
public void run() {
long t0 =System.nanoTime();
long t = 0;
while(t<TASK_TIME*1e6){ t = System.nanoTime() - t0; }
if(countDown!=null) countDown.countDown();
}
}
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactory() {
int counter = 1;
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "Executor thread " + (counter++));
return t;
}
};
// the total duty to be divided in tasks is fixed (problem dependent).
// Increase ntasks will mean decrease the task time proportionally.
// 4 Is an arbitrary example.
// This tasks will be executed thousands of times, inside a loop alternating
// with serial processing that needs their result and prepare the next ones.
int ntasks = 4;
int nthreads = 2;
int ncores = Runtime.getRuntime().availableProcessors();
if (nthreads<ncores) ncores = nthreads;
Batch serial = new Batch(null);
long serialTime = System.nanoTime();
serial.run();
serialTime = System.nanoTime() - serialTime;
ExecutorService executor = Executors.newFixedThreadPool( nthreads, threadFactory );
CountDownLatch countDown = new CountDownLatch(ntasks);
ArrayList<Batch> batches = new ArrayList<Batch>();
for (int i = 0; i < ntasks; i++) {
batches.add(new Batch(countDown));
}
long start = System.nanoTime();
for (Batch r : batches){
executor.execute(r);
}
// wait for all threads to finish their task
try {
countDown.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long tmeasured = (System.nanoTime() - start);
System.out.println("Task time= " + TASK_TIME + " ms");
System.out.println("Number of tasks= " + ntasks);
System.out.println("Number of threads= " + nthreads);
System.out.println("Number of cores= " + ncores);
System.out.println("Measured time= " + tmeasured);
System.out.println("Theoretical serial time= " + TASK_TIME*1000000*ntasks);
System.out.println("Theoretical parallel time= " + (TASK_TIME*1000000*ntasks)/ncores);
System.out.println("Speedup= " + (serialTime*ntasks)/(double)tmeasured);
executor.shutdown();
}
}
Вместо выполнения вычислений каждая партия просто ожидает некоторое время. Программа рассчитывает ускорение , которое теоретически всегда будет равно 2, но может быть меньше 1 (на самом деле снижение ), если значение TASK_TIME мало.
Мои вычисления занимают 1 мс и обычно быстрее. В течение 1 мс я нахожу небольшое ускорение примерно на 30%, но на практике с моей программой я замечаю, что снижение скорости .
Структура этого кода очень похожа на мою программу, поэтому, если бы вы могли помочь мне оптимизировать обработку потоков, я был бы очень признателен.
С уважением.
Ниже, оригинальный вопрос:
Привет.
Я бы хотел использовать многопоточность в моей программе, так как я считаю, что она может значительно повысить ее эффективность. Большая часть времени его работы обусловлена независимыми расчетами.
Моя программа имеет тысячи независимых вычислений (несколько линейных систем для решения), но они просто происходят одновременно небольшими группами из десятков или около того. Каждой из этих групп потребуется несколько миллисекунд для запуска. После одной из этих групп вычислений программа должна некоторое время запускаться последовательно, а затем мне снова приходится решать линейные системы.
На самом деле, можно видеть, что эти независимые линейные системы, которые нужно решить, находятся внутри цикла, который повторяется тысячи раз, чередуясь с последовательными вычислениями, которые зависят от предыдущих результатов. Моя идея, чтобы ускорить программу, состоит в том, чтобы вычислять эти независимые вычисления в параллельных потоках, разделяя каждую группу (количество процессоров, которые у меня есть) на партии независимых вычислений. Так что, в принципе, очереди вообще нет.
Я пытался использовать FixedThreadPool и CachedThreadPool, и это получалось даже медленнее, чем последовательная обработка. Кажется, что создание новых протекторов занимает слишком много времени каждый раз, когда мне нужно решить партии.
Есть ли лучший способ справиться с этой проблемой? Эти пулы, которые я использовал, кажутся подходящими для случаев, когда каждый поток занимает больше времени вместо тысяч меньших потоков ...
Спасибо!
С наилучшими пожеланиями!