Для приложения, выполняющего несколько одинаковых задач вычисления в цикле, будет ли ExecutorService наиболее подходящим решением для распределения задач между ЦП с точки зрения накладных расходов?Является ли ExecutorService самым легким подходом к параллельному исполнению с точки зрения накладных расходов на поток?
Ниже приведено тестовое приложение, которое я построил с использованием этого ответа https://stackoverflow.com/a/28632378/2721750, чтобы узнать, что для двух задач, выполняющихся параллельно на двух физических ядрах Intel Core i5 2,5 ГГц, накладные расходы составляли приблизительно 0,1 миллисекунды за цикл.
Есть ли еще одно решение, которое может помочь уменьшить накладные расходы?
Требование состоит в том, что задачам необходимо получить параметр и вернуть значение из/в основной поток. Это призывы к собственному API, которые я не могу изменить.
package asyncthreadbenchmark;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AsyncThreadBenchmark {
public static Double CalcResult(Integer p)
{
Long startTime = System.nanoTime();
double d = 0;
/* Simulating payload for the given number of milliseconds */
while ((System.nanoTime() - startTime)/1000000 < p)
{
d = Math.PI * Math.pow(Math.log((double)p), Math.E);
}
return d;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
class CalcTask implements Callable<Double> {
Integer p;
CalcTask(Integer parameter) {
p = parameter;
}
@Override
public Double call() {
return CalcResult(p);
}
}
/*
Using Intel Core i5 2.5 GHz dual core, execuction of 10,000 cycles
with 6 ms per task max resulted in 61024-61034 ms total.
That is 0.1 ms overhead for 2 tasks per cycle.
If the savings from running 2 tasks in parallel exceed 0.1 ms
it makes sense to use Executor Service. Otherwise...
*/
ExecutorService executor = Executors.newFixedThreadPool(3);
try {
Integer param1, param2, param3;
param1 = 5;
param2 = 6;
// param3 = 4;
Future aFuture, bFuture, cFuture;
Double a, b, c;
Long startTime = System.nanoTime(), elapsed;
for (long i = 0; i< 10000; i++)
{
aFuture = executor.submit(new CalcTask(param1));
bFuture = executor.submit(new CalcTask(param2));
// cFuture = executor.submit(new CalcTask(param3));
try {
a = (Double)aFuture.get();
b = (Double)bFuture.get();
// c = (Double)cFuture.get();
} catch (InterruptedException | ExecutionException ex) {
// Logger.getLogger(AsyncThreadBenchmark.class.getName()).log(Level.SEVERE, null, ex);
}
}
elapsed = (System.nanoTime() - startTime)/1000000;
System.out.println("Elapsed " + Long.toString(elapsed) + "ms");
}
finally {
executor.shutdown();
}
}
}
Накладные расходы могут быть вызваны тем, что ЦП не являются на 100% доступными (на компьютере работают другие процессы), сборку мусора и т. Д. Вероятно, вы должны попытаться измерить производительность с помощью соответствующего инструмента, такого как jmh. – assylias