2014 dxdy logo

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

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




На страницу Пред.  1 ... 13, 14, 15, 16, 17  След.
 
 Re: Как писать быстрые программы
Сообщение25.11.2025, 08:53 
Аватара пользователя
Dmitriy40 в сообщении #1710562 писал(а):
После чего программа вылетела по нехватке памяти для parfor (интересно какого фига?!).

Мне тоже интересно. Если разберётесь, расскажите, плиз.

 
 
 
 Re: Как писать быстрые программы
Сообщение25.11.2025, 13:48 
Аватара пользователя
Нулевой фактор действительно ускорил в 2.6 раза.

Но вот то, что уменьшение кандидатов в 2 с лишним раза не влияет на скорость, поверить не мог и стал проверять. Взял те самые 48 из 210 вместо 105 из 210. Дважды провёл сравнение на пустом компе.

Не-е, ускорение всё-таки есть. Причём регулярное. Но да, почему-то крошечное. Менее 2%.

Код:
  8   131593       413   492   92   0        509 ms
  9   131596       364   495   133   4        599 ms
  10   131591       330   487   169   11        728 ms
  11   131587       299   479   198   21        913 ms
  12   131575       277   464   222   33        1,234 ms
  13   131586       253   457   242   44        1,802 ms
  14   131610       236   442   257   57        2,598 ms
  15   131577       220   431   273   68        3,249 ms
  16   131611       206   419   283   80        4,324 ms
  17   131604       193   407   293   91        5,650 ms
  18   131579       182   397   301   101        6,988 ms
  19   131593       174   387   304   111        10,261 ms
  20   131590       166   375   310   120        15,919 ms
  21   131597       157   366   315   128        20,012 ms
  22   131580       151   355   318   138        25,810 ms
  23   131588       144   349   319   143        33,423 ms
  24   131572       138   341   322   151        39,577 ms
  25   131573       135   329   323   159        47,103 ms

3min, 40,700 ms


  8   131597       413   492   92   0        479 ms
  9   131595       364   495   133   4        565 ms
  10   131593       330   487   169   11        692 ms
  11   131589       299   479   198   21        871 ms
  12   131579       277   464   222   33        1,192 ms
  13   131590       253   457   242   44        1,770 ms
  14   131613       236   442   257   57        2,575 ms
  15   131573       220   431   273   68        3,211 ms
  16   131616       206   419   283   80        4,282 ms
  17   131608       193   407   293   91        5,601 ms
  18   131588       182   397   301   101        6,927 ms
  19   131597       174   387   304   111        10,209 ms
  20   131591       166   375   310   120        15,723 ms
  21   131604       157   366   315   128        19,720 ms
  22   131585       151   354   318   138        25,526 ms
  23   131589       144   349   319   143        32,789 ms
  24   131576       138   341   322   151        38,688 ms
  25   131577       135   329   323   159        45,958 ms

3min, 36,783 ms


Программу модифицировал вот так:

(PARI)

Код:
{t0=getwalltime();print;

maxp = 7; per = 210; m = vector(maxp,i,[1..i-1]); dob = vector(2*4*6);

\\print;print("m = ",m,"   ");print;

foreach(m[7],m7,
foreach(m[5],m5,
foreach(m[3],m3,
foreach(m[2],m2,
chi = chinese([ Mod(m2,2), Mod(m3,3), Mod(m5,5),Mod(m7,7) ]);
kdob++; dob[kdob] = lift(chi);
))));

dob = Set(dob);

kolper = 4762;


ogrp = 67;

for (ste = 8, 25,

t1=getwalltime(); kol = vector(4); kpod = 0;

mnoper = floor(10^ste / per) - kolper;


for( i = 0, kolper-1,

for( j = 1, kdob,

n = per * (mnoper + i) + dob[j];



if(factor(n,ogrp)[1,1] < ogrp, next);


fac = factor(n); kunp = matsize(fac)[1];

if(fac[1,1] >= ogrp,

kpod++; kdel = 1;

for(i = 1, kunp, kdel *= fac[i,2] + 1);

if(kdel ==  8, kol[3]++;next);
if(kdel ==  4, kol[2]++;next);
if(kdel == 16, kol[4]++;next);
if(kdel ==  2, kol[1]++);

)));

print1("  ", ste,"   ", kpod,"       ");
for(i=1,4,print1(round(kol[i]/kpod*1000),"   "));
print(,"     ", strtime(getwalltime()-t1));

);

print;print(strtime(getwalltime()-t0));print;
}quit

 
 
 
 Re: Как писать быстрые программы
Сообщение25.11.2025, 14:28 
Yadryara в сообщении #1710606 писал(а):
Но да, почему-то крошечное. Менее 2%.
Дык потому что так экономится половина вызовов factor(n,67), приводящих к отказу, а они все суммарно занимают порядка 3с для чисел около 1e25:
Код:
? forstep(i=10^25-10^6-1,10^25-1,2, f=factor(i,67))
time = 3,104 ms.
Вот примерно половина из этих 3с и экономится, а вовсе не из полных 47с (о чём я выше и сказал). Но плюс накладные расходы на организацию ещё одного цикла и довычисление n.

-- 25.11.2025, 14:35 --

И даже с не влезающей ни в какую память таблицей 67# экономия не превысит тех же 3с. Из 47с.

 
 
 
 Re: Как писать быстрые программы
Сообщение25.11.2025, 23:27 
Yadryara в сообщении #1710566 писал(а):
Dmitriy40 в сообщении #1710562 писал(а):
После чего программа вылетела по нехватке памяти для parfor (интересно какого фига?!).
Мне тоже интересно. Если разберётесь, расскажите, плиз.
Не сказать что разобрался, скорее наткнулся снова в другом месте: памяти не хватает factor(), почему было написано про parfor() неясно, возможно именно он выделяет локальную память потокам, вот её и не хватило.

wrest
А Вы случаем не видели как factor() внутри устроена? Там ведь ECM (ну не QS же)? И похоже что seed не случайный, а фиксированный (время разложения не меняется от запуска к запуску)?
А, да, справка по factorint() отвечает что таки ECM, причём дважды (для больших чисел). Но вот про seed интересно.

 
 
 
 Re: Как писать быстрые программы
Сообщение25.11.2025, 23:37 
Dmitriy40 в сообщении #1710659 писал(а):
А Вы случаем не видели как factor() внутри устроена?

Нет я не смотрел. Смотреть надо factorint чтобы не искать ветку с целыми (не удивлюсь если factorint и вызывается).
Судя по опциям (второй параметр) там методов много, в т.ч. и ECM).

Запустите
default(debug,5)
factor(n)

и наслаждайтесь :mrgreen:

 
 
 
 Re: Как писать быстрые программы
Сообщение25.11.2025, 23:59 
wrest
Спасибо, красота!

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 00:10 
Dmitriy40 в сообщении #1710659 писал(а):
Не сказать что разобрался, скорее наткнулся снова в другом месте: памяти не хватает factor(), почему было написано про parfor() неясно,

Задайте
\gm 2
Возможно будет яснее что с памятью

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 05:18 
Аватара пользователя
Вопрос быстрой факторизации важнейший и сложнейший. И конечно заслуживает отдельной темы. (Вроде была такая, может и не одна.) Skipper попытался упростить, а здря. Надо или разбираться по-честному или не лезть в эти дебри.

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 11:43 
Yadryara в сообщении #1710678 писал(а):
Вопрос быстрой факторизации важнейший и сложнейший. И конечно заслуживает отдельной темы.

Так на [не]решении этого вопроса держатся почти все деньги мира и не только деньги. Как только [если] он будет решён, тут же наступит хаос и армагеддон. Так что перспективы его решения в ближайшее время (исходя из того, что вопрос пока не решён) весьма негативные. Считайте, что встроенный в pari/gp алгоритм уже делает факторизацию максимально быстро по возможностям вашего компа.

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 12:39 
wrest
Не совсем так: криптография держится на факторизации больших полупростых, цифр эдак 130+ (а то и 700+), нас же пока что интересуют числа порядка 1e50, причём они часто точно не полупростые (не должны ими быть), для таких вполне можно придумать что-то более быстрое, тем более что полная факторизация нам и не нужна, достаточно убедиться что нет делителей менее кубического корня (это гарантирует что число полупростое), сами оставшиеся два делителя при этом не нужны.
Кроме того, нам не обязательно доводить даже такую проверку до конца, если число не разложилось быстро, можно отбрасывать кандидата и искать относительно легко разложимые кандидаты.
Но ничего из этого PARI не умеет. :-(

-- 26.11.2025, 13:10 --

Dmitriy40 в сообщении #1710699 писал(а):
Кроме того, нам не обязательно доводить даже такую проверку до конца, если число не разложилось быстро, можно отбрасывать кандидата и искать относительно легко разложимые кандидаты.
А можно и не отбрасывать, а запустить факторизацию в отдельном потоке (ага, на каждое число) и ждать что произойдёт раньше, закончится (так или иначе) факторизация всех чисел для старого кандидата (или он будет отброшен) или для нового более лёгкого. Наплодить так потоков миллион (для сотен тысяч кандидатов) и что-то да разложится ... :mrgreen: Этого PARI тоже не умеет.

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 13:45 
Продолжение таблицы (в 4 потока):
Код:
10^51:   131585       65     213     295     240      7h, 11min, 49,637 ms
10^52:   131581       64     210     295     238      10h, 17min, 25,888 ms
10^53:   131608       61     207     294     241      10h, 36min, 35,702 ms
10^54:   131575       62     204     292     241      14h, 44min, 29,260 ms
10^55:   131598       59     201     290     244      14h, 51min, 49,006 ms
10^56:   131585       59     198     291     242      18h, 56min, 14,223 ms
10^57:   131578       58     196     288     245      22h, 27min, 50,890 ms
10^58:   131606       57     195     284     244      28h, 39min, 5,653 ms
10^59:   131590       55     191     285     247      33h, 5min, 7,190 ms

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 14:35 
Аватара пользователя
Благодарю. В принципе можно было уже не считать, картина-то ясна. Подставлю актуальные количества:

Код:
Делителей:             2       4       8      16
Чисел:                 1       1      17       3
10^51:   131585       65     213     295     240     
10^52:   131581       64     210     295     238     
10^53:   131608       61     207     294     241     

Либо не 3, а 4 числа с 16 делителями. И для них-то актуален интервал до корня 4-й степени.

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 16:43 
Ещё бы найти алгоритм гарантирующий отсутствие делителей до заданного порога ... Что-то кроме перебора делителей я таких не вижу.
Либо плюнуть на гарантию и отбрасывать кандидаты если делитель не нашёлся быстрым методом, даже если он и есть (можно пропустить кортеж).

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 16:59 
Dmitriy40 в сообщении #1710699 писал(а):
Но ничего из этого PARI не умеет. :-(

Ну всетки не ничего, вот это же
Dmitriy40 в сообщении #1710699 писал(а):
убедиться что нет делителей менее кубического корня (это гарантирует что число полупростое),
умеет: factorint(n,n^(1/3)\1)

Ну и
Dmitriy40 в сообщении #1710699 писал(а):
если число не разложилось быстро, можно отбрасывать кандидата и искать относительно легко разложимые кандидаты.
тоже можно, зависит от "достаточно быстро". User manual:
Цитата:
\\ Time-bounded partial factorization
default(factor_add_primes,1);
timefact(N,sec)={
F = alarm(sec, factor(N));
if (type(F) == "t_ERROR", factor(N, 2^24), F);
}

We either return the factorization directly, or replace the t_ERROR result by a simple bounded factorization factor(N, 2^24). Note the factor_add_primes trick: any prime larger than 2^24 discovered while attempting the initial factorization is stored and remembered. When the alarm rings, the subsequent bounded factorization finds it right away.
Caveat. It is not possible to set a new alarm within another alarm code: the new timer erases the parent one.
Caveat2. In a parallel-enabled gp, if the code involves parallel subtasks, then alarm may not return right away: il will prevent new tasks from being launched but will not interrupt previously launched secondary threads. This avoids leaving the system in an inconsistent state.

При чем, можно же не выбрасывать трудные кандидаты, а складывать "на потом", отдавать другой программе и т.п. :mrgreen:

 
 
 
 Re: Как писать быстрые программы
Сообщение26.11.2025, 17:49 
wrest в сообщении #1710721 писал(а):
умеет: factorint(n,n^(1/3)\1)
Только здесь уже просто factor(), не factorint().
Ну так это будет тупой перебор делителей. Это нереально долго.
wrest в сообщении #1710721 писал(а):
тоже можно, зависит от "достаточно быстро".
Секунда слишком много, надо миллисекунды, если не ещё меньше. Это первое.
Второе, alarm+factor глючит! Когда я писал факторизацию чисел 70+ знаков то на это наткнулся и писал об этом в теме про PARI (и ещё штук 7 сообщений далее). Причём aitap там дальше увидел что ошибка в исходнике (плохая синхронизация потоков с таймером).
В третьих, даже в вашей же цитате указано что в многопточном режиме глючит.

 
 
 [ Сообщений: 253 ]  На страницу Пред.  1 ... 13, 14, 15, 16, 17  След.


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