Как оптимизировать static методы + вопросы параллельных вычислений?

Есть класс MyMath, в котором реализованы математические вычисления в виде static методов. Каждый из static методов получает параметр и при вычислениях пользуется только им или локальными переменными-примитивами метода (т.е. потокобезопасен). Некоторые из методов вычисляются довольно долго (некоторые даже в пределах нескольких секунд).
Предполагается вызов этих методов из множества разных потоков. Эти потоки создаются в разных местах наподобие:
Runnable myTask = () -> { ... у1=MyMath.calc1(x1); ... уN=MyMath.calcN(xN) ...};
new Thread(myTask).start()
;
Как грамотно с точки зрения производительности и юзабельности кода все это создать (пока статик методы классы + вызов из создаваемых потоков)?
Может единый для всех ThreadPoolExecutor + помещаем в него вычисления оформленные как Callable ?
Может при динамическом создании потока в него засунуть тело функции (тогда будет дублирование, что плохо, но скорость выполнения возрастет) ?
Аналога c-ного inline я так понимаю нет.

Пусть
class MyMAth {
  public static double myCalc(double x) {
     double res=0;
     for(i=0;i< 1000000;i++) 
       res += страшная матан формула, зависящая от i и от x;
     return res;
  }
}


Если допустим 50 потоков вызывают MyMath.myCalc(x) то процессор при переключение потоков каждый раз: при прерывании вычисления функции останавливает очередную итерацию цикла + сохраняет состояние переменных, а при ее пробуждении - восстанавливает состояние этого же цикла для других переменных + продолжает вычислять.
Вопрос 2 - При выполнении он дополнительно копирует код static функции (который идентичен) отдельно для каждого процесса (чтобы в дальнейшем кешировать его в блоке кода для каждого ядра) или нет? Или при переключении между потоками просто копирует/восстанавливает состояние регистров и прочих служебных областей, а потом каждый раз копирует снова участок кода static функции?
  • Вопрос задан
  • 145 просмотров
Пригласить эксперта
Ответы на вопрос 1
Applez
@Applez
Разраб
Создание потока затратная операция, лучше всегда иметь пул (если вы можете примерно прикинуть сколько необходимо потоков, то FixedThreadPool, если нет, то позвольте JVM самой выбрать и используйте CachedThreadPool). По поводу inline-methods, уже миллион раз обсуждалось, JVM довольная умна, чтобы решить, нужно ли инлайнить методы, нужно только ее прогреть. Инфу можно почерпнуть отсюда. Если быть конкретнее, то вот этот абзац:

Method Inlining
The frequency of virtual method invocations in the Java programming language is an important optimization bottleneck. Once the Java HotSpot adaptive optimizer has gathered information during execution about program hot spots, it not only compiles the hot spot into native code, but also performs extensive method inlining on that code.

Inlining has important benefits. It dramatically reduces the dynamic frequency of method invocations, which saves the time needed to perform those method invocations. But even more importantly, inlining produces much larger blocks of code for the optimizer to work on. This creates a situation that significantly increases the effectiveness of traditional compiler optimizations, overcoming a major obstacle to increased Java programming language performance.

Inlining is synergistic with other code optimizations, because it makes them more effective. As the Java HotSpot compiler matures, the ability to operate on large, inlined blocks of code will open the door to a host of even more advanced optimizations in the future.

Если ваша задача выполняется без блоков/прерываний на ожидания внешних действий, то повлиять на работу процессора/JVM и всего прочего вы не сможете, предлагаю в этом случае забыть о процессорах/регистрах/etc.
По остальному, почитайте документацию, узнаете "что во что" компилируется и как работает, описывать это здесь - долго.
Удачи.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы