LINUX.ORG.RU

Оптимизация вычислений на крестах


0

2

Я уже в торсионном треде спрашивал @AntonI про числодробилки на плюсах, но возможно кто-нибудь ещё сможет дать совет по тому, как правильно оптимизировать вычисления на плюсах (фортран тоже сойдёт на самом деле, но нужны веские аргументы, как впрочем и питон с нумпаями).

Я вычисляю значение комплекснозначной функции от трёх действительных аргументов (плюс ещё порядка тридцати действительных параметров, которые при вычислении фиксированы на каждую итерацию фита). Пока я взял фортрановский код, соответствующий данной статье, и переписал его в виде класса с методами const и double. Пример ниже приведён. Таких функций я должен буду насчитывать по миллиарду раз на только одну итерацию фита, поэтому и встаёт вопрос об оптимальном написании кода.

Заголовочный файл вот такой:

#include <complex>
typedef std::complex<double> complex;
class ff_t
{
    private:
        double mro, gro, mrp, grp, mf2, gf2, mf0, gf0, msg, gsg;
        complex bt1, bt2, bt3, bt4, bt5, bt6, bt7;
        double mpi, mpi2;
        double sqr (double x) const {return x*x;}
    public:
        ff_t ();
        complex xi1 (double qq, double s1, double s2) const;
};

Кусок файла с кодом:

#include "ff.hpp"
#include <cmath>

complex ff_t::bw (double s, double m, double g, int l) const
{
    const auto mp = 4*sqr (mpi);
    const auto msq = sqr (m);
    const auto w = std::sqrt (s);
    double wgs = 0.0;
    if (w>2*mpi) {
        auto qs = std::sqrt (std::abs ((s-mp)*s))/w;
        auto qm = std::sqrt (std::abs ((msq-mp)*msq))/m;
        const int ipow = 2*l+1;
        wgs = g*(msq/w)*std::pow(qs/qm, ipow);
    }
    return complex (msq, 0.)/ complex (msq-s, -wgs);
}

complex ff_t::xi1 (double qq, double s1, double s2) const
{
    // check phase space
    auto s3 = qq - s1 - s2 + 3*mpi2;
    if ((s3 <= 0.) or (s2 <= 0.))
        return complex(0., 0.);
    const auto f134 = -1./3. * ((s3-mpi2)-(s1-mpi2));
    const auto f15a = -1./2. * ((s2-mpi2)-(s3-mpi2));
    const auto f15b = -1./18.* (qq-mpi2+s2)*(4.*mpi2-s2)/s2;
    const auto f167 = -2./3.;

    const auto fro1 = bw (s1, mro, gro/*o*/, 1);
    const auto frp1 = bw (s1, mrp, grp, 1);
    const auto fro2 = bw (s2, mro, gro, 1);
    const auto frp2 = bw (s2, mrp, grp, 1);
    const auto ff21 = bw (s1, mf2, gf2, 2);
    const auto ff22 = bw (s2, mf2, gf2, 2);
    const auto fsg2 = bw (s2, msg, gsg, 0);
    const auto ff02 = bw (s2, mf0, gf0, 0);

    return
         bt1*fro1      + bt2*frp1+
         bt3*f134*fro2 + bt4*f134*frp2
       - bt5*f15a*ff21 - bt5*f15b*ff22
       - bt6*f167*fsg2 - bt7*f167*ff02;
}

И флаги компиляции:

CFLAGS=-pthread -std=c++14 -m64 -fext-numeric-literals
CFLAGS += -Wall -Werror -Wpacked -malign-double -O3\
          -mpreferred-stack-boundary=8 -Wfatal-errors
★★★★★
Ответ на: комментарий от Siborgium

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

anonymous
()
Ответ на: комментарий от Siborgium

потому, например, что w — это sqrt(s),

sqrt(abs((s-mp)*s)) / w = 
sqrt(abs((s-mp)*s)) / sqrt(s) = 
sqrt(abs((s-mp)*s / s)) =
sqrt(abs(s-mp))

со вторым выражением то же самое.

anonymous
()
Ответ на: комментарий от anonymous

Я это ... скажу за фортран и вставлю свои 5 копеек

Честно признаюсь, в крестах опыта нет. Но при всем этом если задача стоит только считать (а не составная часть иного большого ПО), то стоит ли городить объекты и методы?

Не проще ли будет фигануть всё массивами, чтобы компилятор сам оптимизировал как ему надо? Сообразит ли компилятор как ему лучше соптимизироваться, если он видит объект? В фортране я наблюдал порядочное ускорение при «переворачивании» прямоугольного массива, тут можно будет попробовать сделать то же самое, если много входных данных.

Пусть входные данные - комплексный массив, параметры - еще 2 массива, это всё передается процедуре xi1 и в ней с нужными элементами массива всё происходит.

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

Готов из спортивного интереса попробовать.

И в каком месте происходит полтора миллиона проб?

sshestov ★★
()

полтора миллиона

Полтора миллиарда. Монте-Карло данные.

Готов из спортивного интереса попробовать.

Оригинальный фортрановский код выглядит как-то так (я кучу всего повыкидывал правда): https://godbolt.org/z/x5saWW

luke ★★★★★
() автор топика
Ответ на: комментарий от anonymous

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

luke ★★★★★
() автор топика
Ответ на: комментарий от luke

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

КМК именно тогда (когда есть массив (дохрена,3) или (3,дохрена)) компилятор может соптимизировать запуск функции f3pi. На одном запуске особо то и нечего оптимизировать.

Ну и там дальше могут тоже начаться детали красоты: как и когда появляются/меняются эти 30 коэффициентов. Они одинаковые для различных начальных (qq,sa,sb)? Или иногда должны меняться? Их инициализацию, КМК, логично вынести за функцию f3pi

sshestov ★★
()
Ответ на: комментарий от luke

я просто на её примере показал как можно ещё упростить. сам-то алгоритм, ведь, никуда не делся.

anonymous
()
Ответ на: комментарий от luke

Оригинальный фортрановский код

PI = 3.14159

movss

Там флоаты, я боюсь точности не хватит

может зря боишься?

а сколько всего планируется итераций по 1.5e9 циклов?

anonymous
()
Ответ на: комментарий от anonymous

а также обычные real во всех коэффициентах и деление в самом начале выражений в коэффициентах F135, F15A, F15B, F167 :)

Но ускорение может пойти вовсе не здесь, а позже.

sshestov ★★
()
Ответ на: комментарий от anonymous

может зря боишься?

Код из середины девяностых, конечно у них тогда мощности были максимум первопни с MMX, вот и считали всё флоатами.

Да и насчитывать надо было лишь 500 тысяч, а не полтора миллиарда.

luke ★★★★★
() автор топика
Ответ на: комментарий от anonymous

а сколько всего планируется итераций по 1.5e9 циклов?

Зависит от того, как фит будет сходиться.

Тут бы и градиент надо посчитать (впрочем, он не такой уж и сложный)

luke ★★★★★
() автор топика

Сообразит ли компилятор как ему лучше соптимизироваться, если он видит объект?

Да.

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

Как и в C++.

И не нужно париться с конст и прочими атрибутами.

Честно говоря, не знаю, зачем ТС-у const’ы. Хочет – пожалуйста, ни вреда, и особой пользы от них нет.

Siborgium ★★★★★
()
Ответ на: комментарий от luke

не, ну если была задача посчитать полтора миллиарда итераций/seed-ов, то с этого и нужно начинать - как они попадают и как хранятся (и может отсеиваются по пути) и вместе с ними уж оптимизироваться.

Если занимаемся красотой ООП, то вопросов нет.

В субрутине f3pi КМК не нужно вычислять коэффициенты (хотя здесь оно и происходит один раз). Лучше это снаружи сделать, а дальше f3pi подсовывать двумерные массивы наборов qq,sa,sb. Без примеров оно сильно абстрактно, мне то чего абстрактно писать/пробовать?

sshestov ★★
()
Последнее исправление: sshestov (всего исправлений: 1)
Ответ на: комментарий от sshestov

Без примеров оно сильно абстрактно, мне то чего абстрактно писать/пробовать?

Не надо.

C++ используется в основном из-за root.cern Можно логику и на фортране написать, оставив чтение/запись на плюсы; имхо разницы особо не будет, хотя ногу прострелить можно выравняв где-нибудь случайно не туда.

Так-то у меня коллега вообще всё на нумпае пишет, у него если в память массивы влазят то получается уже довольно неплохо, он за каникулы наоптимизировал программу до того, что с 20 дней на один интеграл она стала требовать только пару часов.

luke ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Простите, настроение скверное было.

luke ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.