2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1 ... 23, 24, 25, 26, 27, 28, 29 ... 32  След.
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 04:38 
wrest
Спасибо.
Круто.
Я знал что более простой код может обогнать, главное нормальный язык (в данном случае С). ;-)

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 05:10 
Аватара пользователя
Пошёл пока в старый 2.15.4

Это какая-то фантастика:

Код:
1000000/189   1min, 32,875 ms
1000000/200         14,550 ms

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 05:13 
Уменьшите интервал до 100тыс и выведите список найденных n (их будет по 19-20шт) и сравните два списка, они должны быть очень похожи. Я этого кажется так и не сделал.

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 05:53 
Аватара пользователя
factor:

Код:
6467627468614808795443546523718456286724685969
10855657655909537144302664881818184651275425169
17837782644434335974597318078551943146856055569
17953860816473813836607079365105605973730933969
19384879862288562657193820285109061930342577169
19573908347981309215091139060050204557506410769
43326346950683953152819762794766111859136666769
45041367532041930418402718087800070937627953169
49421139193262703820557584654761594041768621969
52556626259340931919271848023566857910792017169
70629034151179006957076184297672702774829409169
86848779360426522284226702093107834220207674769
95685861066562423865926354821606252040116895569
96086399581149238781082566691809207170005309969
100372574613531856120589246292537737322831847569
112355237139836375180308359023454780996710105169
123328524257101956309507808393035626176024202769
129427445762717684450597756148600210988861193169
131176876869383807327448427238043358652394439569

100000/19

8,912 ms

forprime:

Код:
6467627468614808795443546523718456286724685969
10855657655909537144302664881818184651275425169
17837782644434335974597318078551943146856055569
17953860816473813836607079365105605973730933969
19384879862288562657193820285109061930342577169
19573908347981309215091139060050204557506410769
43326346950683953152819762794766111859136666769
45041367532041930418402718087800070937627953169
49421139193262703820557584654761594041768621969
52556626259340931919271848023566857910792017169
58000830170093676229974723226119281245563981969
70629034151179006957076184297672702774829409169
86848779360426522284226702093107834220207674769
95685861066562423865926354821606252040116895569
96086399581149238781082566691809207170005309969
100372574613531856120589246292537737322831847569
112355237139836375180308359023454780996710105169
123328524257101956309507808393035626176024202769
131176876869383807327448427238043358652394439569

100000/19

1,435 ms

Появляется 580... , но исчезает 1294...

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 09:20 
Аватара пользователя
Менял разное, быстрее не стало. Ну вот один из вариантов.

Мне представляется, что некоторые коменты избыточны. И очень не люблю когда они за правый край вылезают. Вот пример более лаконичных:

Код:
\\Начало проверки конкретной цепочки

nfac = vector(#v); \\ Кол-во факторов пока нулевое

ch = vector(#v,d,n+d-1);  \\ Частное пока равно цепочке-кандидату

forprime(p=59,2^20,

d=(n+#v-1)%p; if(d>=#v, next); d=#v-d; nfac[d]++; ch[d] \= p;

if(nfac[d] >nu[d]-1                                , next(2)); \\ Перебор
if(nfac[d]==nu[d]-1 && !ispseudoprime(ch[d]/v[d],1), next(2)); \\ Ровно  и составное
if(nfac[d] <nu[d]-1 &&  ispseudoprime(ch[d]/v[d],1), next(2)); \\ Меньше и простое
);
   kcep++;
   print(n);
);

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 09:23 
Dmitriy40 в сообщении #1711602 писал(а):
Я знал что более простой код может обогнать, главное нормальный язык (в данном случае С).

Ну я скомпилировал "как есть", на Си-шный код не смотрел. Возможно, типизацией счётчиков циклов и т.п. ещё можно будет немного ускорить (если транслятор в Си этотуже не сделал).

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 09:30 
Аватара пользователя
Ещё можно весь nu[] сразу на единичку понизить, но это совсем копейки.

И непонятно что дальше делать. То ли пытаться рабочую программу исправлять. То ли эту тестовую затачивать под многопоточность.

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 12:33 
Dmitriy40
Смотрю исходный код forprime
Там крайне заморочено всё. Разрабы очень старались, чтобы было безопасно (пока возможно, используется тип ulong, потом переключается в GEN) , чтобы таблица по которой итерируется (или её куски) помещалась в L2 кэш то есть под forprime() решетом готовится своя таблица простых по которым он потом идёт, и все такое сильно запутанное.
А вот в движке факторизации, когда используется тот же factor(n,D) с ограничением по множителям, таких заморочек нет - там они просто ходят по готовой primetab, но это непубличная таблица и как я понял, сделано так специально.
Тоже самое по ispseudoprime(). В движке факторизации есть функция ifac_isprime() которая используется для проверки полученных делителей и частного на простоту, но к этому моменту уже ясно что маленькие делители отсутсвуют. А "пользовательская" ispseudoprime() запутанней, т.к. в ней может ещё быть флаг, а в тестируемом числе могут быть маленькие делители и т.п..
Думаю, что было бы вполне безопасно использовать primetab и ifac_isprime(), но моих знаний не хватает пока как сделать это в пользовательской функции, т.е. довести до ума результат трансляции gp2c не влезая (не перекомпилируя) в ядро.

Ранее сделанная omega_upto() как раз ходит по primetab и использует ifac_isprime(0)...

Yadryara
Я кстати выжал из ИИ ещё одну функцию, omega_range() которая считает количество различных простых множителей не с двойки до лимита, а в заданном диапазоне, но пока не уверен что она вам нужна :D
код: [ скачать ] [ спрятать ]
Используется синтаксис C
/* Returns:
 *   k = number of distinct prime factors of n in [l, u], if k <= f
 *       and n is squarefree,
 *   0 otherwise.
 *
 * Arguments:
 *   n: positive integer (t_INT)
 *   f: maximum allowed number of distinct primes in [l, u] (t_INT)
 *   l: lower bound for primes (t_INT, >= 2)
 *   u: upper bound for primes (t_INT, >= l)
 */

GEN
omega_range(GEN n, GEN f, GEN l, GEN u)
{
    pari_sp av = avma;
    long F, nb = 0;
    ulong L, U;

    if (typ(n) != t_INT || signe(n) <= 0) pari_err_TYPE("omega_range", n);
    if (typ(f) != t_INT || signe(f) <= 0) pari_err_TYPE("omega_range", f);
    if (typ(l) != t_INT || typ(u) != t_INT) pari_err_TYPE("omega_range", l);
    if (cmpii(l, u) > 0 || cmpiu(l, 1) <= 0) pari_err_TYPE("omega_range", l);
    if (cmpiu(n, 1) <= 0) return gen_0;

    F = itos(f);
    if (F <= 0) return gen_0;

    L = itou(l);
    U = itou(u);
    if (L > U || L < 2) return gen_0;

    n = absi(n);

    /* Обработка 2, если в диапазоне */
    if (L <= 2 && 2 <= U)
    {
        if (!mod2(n))
        {
            long v = vali(n);
            if (v > 1) { set_avma(av); return gen_0; }
            nb++;
            if (nb > F) { set_avma(av); return gen_0; }
            n = shifti(n, -v);
            if (is_pm1(n)) goto done;
        }
    }

    /* Trial division по primetab */
    {
        long i, lim = lg(primetab);
        for (i = 1; i < lim; i++)
        {
            ulong p = itou(gel(primetab, i));
            if (p > U) break;
            if (p < L) continue;

            if (dvdii(n, utoipos(p)))
            {
                long v = Z_lvalrem(n, p, &n);
                if (v > 1) { set_avma(av); return gen_0; }
                nb++;
                if (nb > F) { set_avma(av); return gen_0; }
                if (is_pm1(n)) goto done;
            }
        }
    }

    /* Проверка остатка: если он простой и в [l, u] — учитываем */
    if (!is_pm1(n))
    {
        if (cmpiu(n, L) >= 0 && cmpiu(n, U) <= 0)
        {
            if (ifac_isprime(n))
            {
                nb++;
                if (nb > F) { set_avma(av); return gen_0; }
                goto done;
            }
        }
    }

done:
    set_avma(av);
    return (nb >= 1) ? stoi(nb) : gen_0;
}

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 12:45 
Аватара пользователя
wrest в сообщении #1711629 писал(а):
Я кстати выжал из ИИ ещё одну функцию, omega_range() которая считает количество различных простых множителей не с двойки до лимита, а в заданном диапазоне, но пока не уверен что она вам нужна :D

Конечно нужна. Причём уже прямо сейчас. Для фильтрации выше $2^{20}$.

Я уже переделал рабочую прогу и запустил одну в PARI, а другую скомпилированную. На одной и той же задаче. Вроде вторая догоняет первую.

И вот в этой проге я фильтрацию по pq и pqrs пока делаю через numdiv. Вот кстати табличка приближений получилась:

Код:
p                                                                         *   
pq                                                                      *     
pqrs                                                           *     *   *     
                                                         1234567890123456789012
1417259285255945755205702390368396120923136018602841       11  11   111 111  1       11
1110868685937233724975985952484764844946015479906841       11 111    11 1111 1       12
1378911273834917718166937033282080460055307043318041        1  111  1111111   1      12
1514922838640882696128778463873332184275366967359641      1 11111  1 1  111  1       12
1537106286503832141453607402241535489551006751671641       111 1 11  1  1111         12
1775003725910225161858951827182873007074371919908441      11   1 1 111  1111 1       13
1382218513561494410938962042095526294585605066620441     11 1 111    11 11111 1      14
1522096028340776538921413879412639769348374487876441     1   1 11 11 1 1111   1      12
1471592286710239418671790755514266007322386233646041      1  1 1 1  11  111  1       10
1488508607464027054659984663314777609123640440030041         1111111111 111 111      16
1030633254297116893931202731594319684231219366676441         1111    1111111 1       12
1579909261756993990645370539667460330408671892503641     11   1111 111 11111 1       15

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 13:01 
Yadryara в сообщении #1711630 писал(а):
Конечно нужна. Причём уже прямо сейчас. Для фильтрации выше 2^20

Тогда, если пересоберёте pari с ней (всё то же самое -- функцию в конец ifactor1.c, плюс добавить объявление в paridecl.h
GEN omega_range(GEN n, GEN f, GEN l, GEN u);
и соответсвующий
install(omega_range,GGGG)
при запуске ./gp из папки pari

Но проверьте, что она работает как вы ожидаете, ибо могут быть сюрпризы.
n - факторизуемое число
f - количество разных простых множителей, при превышении которого возвращать ноль (проверяется остаток (частное) если он композитный, то считается, что в нём больше одного множителя)
l - нижняя граница для множителей
u - верхняя граница для множителей

параметра s больше нет: при обнаружении кратных множителей функция всегда вовращает ноль
Внимание! Функция идёт по готовой таблице простых, которая создаётся при старте интерпретатора и не может меняться после. Сейчас эта таблица содержит простые не превышающие 2^20, так что вам надо запускать pari с установкой нужного вам primelimit
при primelemit=2^32 таблица займёт 10 гигабайт памяти!
Почитайте про primelimit тут: https://pari.math.u-bordeaux.fr/dochtml ... aults.html

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 13:48 
Аватара пользователя
Результаты тестов отличные. Старое время было 140-150 минут на юнит.
Новые времена:

В интерпретаторе PARI 2.17.0 — 80 минут на юнит.
Скомпилированная в PARI 2.15.4 — 41 минута на юнит.

В интерпретаторе PARI 2.18.0 пока не знаю как запустить, где создать папку с помощью mc...

И, соответственно, мне сначала надо проверить как работает без новой омеги...

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 13:58 

(Оффтоп)

Yadryara в сообщении #1711634 писал(а):
Результаты тестов отличные.

Ещё бы понять что вы там тестируете :x
Если вы думаете, что участники поале каждого вашего поста читают 100 предыдущих ваших постов по форуму чтобы понять о чём вы пишете, то боюсь это не так :) Если хотите чтобы вас понимали, делайте посты по возможности аамодостаточными, со ссылками на предыбущее обсуждение и т.п.

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 14:53 
Аватара пользователя
Слушаюсь. И повинуюсь :-)

Рабочую программу тестирую. Да она уже почти в боевом режиме — ищет цепочки в 9 потоков. Я вам уже её присылал, теперь могу прислать актуальную. Или показать кусок, где предполагается ускорить счёт, например с помощью вашей омеги.
Как я ранее писал, о 32-й степени 2-ки речь не идёт, а идёт пока о 25-й.

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 15:49 
Yadryara в сообщении #1711634 писал(а):
В интерпретаторе PARI 2.18.0 пока не знаю как запустить, где создать папку с помощью mc...

Тут надо уточнять что именно вы хотите запустить. Этот "пересобранный" вами из измененного исходного кода экземпляр pari/gp (где есть функция omega_upto()у вас установлен "локально", основная библиотека (libpari) тоже установлена локально. Поэтому этот экземпляр не сможет запускать (как мне представляется) скомпилированные при помощи gp2c пользовательские функции, т.к. gp2c будет их компилировать и потом линковать с "системной" библиотекой libpari .

(Оффтоп)

Запускать пересобранный инстанс, если вынаходитесь в папке pari (где находится исполняемый файл интерпретатора, вернее симлинк - это типа ярлыка - на него, но это не важно сейчас) можно командой
./gp

Если вы в любой другой папке, то надо указывать полный путь к исполняемому файлу интерпретатора, это будет что-то вроде
/home/yadryara/pari/gp
Чтобы запустить скрипт с именем myscript.gp находящийся в папке /home/yadryara/scripts универсальная команда будет
/home/yadryara/pari/gp /home/yadryara/scripts/myscript.gp

Это примерный аналог того как сделано и в windows. Если у вас исполняемый файл скажем myprog.exe находится в папке c:\programs\thisprog\myprog.exe а файл который вы хотите указать как аргумент вызова находится в папке d:\myfiles\ и называется file_to_process.txt то вы в командной строке, независимо от папки где находитесь, можете написать полные пути
c:\programs\thisprog\myprog.exe d:\myfiles\file_to_process.txt
с теми же примерно нюансами что будет в этом случае считаться "рабочей папкой"

 
 
 
 Re: Как писать быстрые программы
Сообщение04.12.2025, 16:25 
Как я понимаю сейчас есть варианты:
1a. factor on ubuntu in interpretator
1c. factor on ubuntu after compile
1w. factor on win in interpretator
2c. omega_upto on ubuntu after compile
3c. omega_range on ubuntu after compile
4a. forprime on ubuntu in interpretator
4c. forprime on ubuntu after compile
4w. forprime on win in interpretator
И про какой из них речь вообще непонятно.

 
 
 [ Сообщений: 467 ]  На страницу Пред.  1 ... 23, 24, 25, 26, 27, 28, 29 ... 32  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group