2014 dxdy logo

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

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




На страницу Пред.  1 ... 47, 48, 49, 50, 51, 52, 53 ... 58  След.
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:02 
Аватара пользователя
Dmitriy40
Наверное не поняли меня. Я думаю, что придётся или более ранний цикл нагружать или ещё один цикл добавить, как в этом примере:

Было:

Код:
for(j = 1, #ostmes,
if(nu[ostmes[j]] - kolfac[ostmes[j]] == 1,

Стало:

Код:
ostmes1=[]; for(j = 1, #ostmes,
if(nu[ostmes[j]] - kolfac[ostmes[j]] == 1, ostmes1 = concat(ostmes1,ostmes[j]) ));

for(j = 1, #ostmes1,

Вроде коротенький доп. цикл не должен много времени отъесть. Зато уж дальше проверяться будут только те места, которые подходят для такой проверки.

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:10 
Yadryara в сообщении #1719893 писал(а):
Но что делать если длина #ostmes1 всё-таки превысит 12?

А вот вопрос на скольких потоках запускать проверку количества делителей не такой уж простой. Тут нужны предположения о распределении времён факторизации.
Если мы параллельно факторизуем например 10 чисел, и минимальное время факторизации (у какого-то числа из этих 10) составляет 50мс, то мы потратим общего времени (сумма по всем потокам) 500мс, а реального 50мс если свободных для занятия потоков будет 10. Но с другой стороны, мы хотим чтобы какими-то полезными вычислениями были заняты все потоки и всегда.
Я бы сказал так, что на параллельную факторизацию надо выделять столько потоков, чтобы в них попало число с "небольшим" временем факторизации, с какой-то заданной нами вероятностью. Короче, вопрос туманный, покашта.

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:27 
Аватара пользователя
wrest в сообщении #1719900 писал(а):
Я бы сказал так, что на параллельную факторизацию надо выделять столько потоков, чтобы в них попало число с "небольшим" временем факторизации. Короче, вопрос туманный, покашта.

Я акцентирую вопрос на другом. Теперь с этой предварительной записью, комп будет точно знать, какое количество мест надо проверять (они все уже будут в векторе ostmes1). Выше я показывал, что их может быть и 5 и 10. Ну так вот, допустим их 13, что будет делать parfor или parvector, уж не знаю кто. Он попытается запустить 12 потоков (потому что больше нельзя), а ещё 1 отложить? Или что? Или это надо как-то настраивать?

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:30 
Yadryara в сообщении #1719901 писал(а):
Ну так вот, допустим их 13, что будет делать parfor или parvector, уж не знаю кто. Он попытается запустить 12 потоков (потому что больше нельзя), а ещё 1 отложить?

Да. Запустит столько сколько сможет, по мере освобождения потоков будет запускать следующие вычисления.

-- 11.03.2026, 13:36 --

Yadryara в сообщении #1719901 писал(а):
Или это надо как-то настраивать?

Да, можно настраивать при помощи default(nbthreads), с некоторыми ограничениями (нельзя сделать больше потоков чем может обеспечить CPU).

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:37 
wrest в сообщении #1719902 писал(а):
по мере освобождения потоков будет запускать следующие вычисления.
Только не вычисления, а конкретно итерации parfor, следующие команды PARI выполняться не будут до полного завершения parfor. А то слово "вычисления" можно понять по разному.

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:39 
Dmitriy40 в сообщении #1719903 писал(а):
Только не вычисления, а конкретно итерации parfor, следующие команды PARI выполняться не будут до полного завершения parfor. А то слово "вычисления" можно понять по разному.

Да, "итерации". Искал слово вместо "поток".

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:47 
wrest в сообщении #1719902 писал(а):
нельзя сделать больше потоков чем может обеспечить CPU
Вот это кстати тоже недостаток PARI: так бы запустить вообще сразу все числа и пусть постепенно раскладываются с примерно одинаковой скоростью (с арбитражем времени вполне справится ОС), при первой же "ошибке" сразу всё останавливается. Правда это выгоднее лишь если первые числа не дают причины отбросить цепочку, что для реальных данных слишком редко случается и на общую картину уже не влияет.

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 13:57 
Dmitriy40 в сообщении #1719906 писал(а):
Вот это кстати тоже недостаток PARI: так бы запустить вообще сразу все числа и пусть постепенно раскладываются с примерно одинаковой скоростью (с арбитражем времени вполне справится ОС), при первой же "ошибке" сразу всё останавливается.

Вы, видимо, исходите из того, что CPU ничем "серьезным" не занят кроме конкретного скрипта pari. Типа всё делается однопоточно и только вот этот parfor в многопотоке.
Но я думаю, что Yadryara будет запускать несколько сессий одновременно (для обсчёта "комплектов" или как оно там называется), так что потоки CPU будут заняты соседними сессиями pari.
Поэтому многопоточность надо использовать экономно, на мой взгляд. Если в среднем из 20 чисел "быстроотсеиваемых" половина, то запускать скажем в четыре потока, рассчитывая на то, что в первом же наборе окажется "быстроотсеиваемое" число которое прервёт parfor.

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 14:05 
Аватара пользователя
wrest в сообщении #1719908 писал(а):
Но я думаю, что Yadryara будет запускать несколько сессий одновременно

Да подождите, я же ещё с parfor-ом не понял. Не получается так просто заменить for на parfor. Он на next(2) ругается.

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 14:57 
Yadryara в сообщении #1719910 писал(а):
Он на next(2) ругается

Плохими словами? Что-то про экспорт? :D

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 15:25 
Аватара пользователя
Код:
yadryara@DESKTOP-QPP2F5P:~/Parfor$ gp2c -g Test_11_5.gp > Test_11.gp.c  &&  gcc -o Test_11 Test_11.gp.c main.c -lpari -lm   &&  ./Test_11
Error:Test_11_5.gp:302: next not allowed here
next(2)

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 15:40 
Yadryara
У parfor синтаксис отличается от for
Почитайте что пишут в
??parfor
Или тут: https://pari.math.u-bordeaux.fr/dochtml ... mming.html
Или разберите синтаксис тут: post1719845.html#p1719845

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 16:17 
Yadryara
Next надо делать не совсем внутри parfor, а в его sequential части (которая выполняется уже не параллельно), которая на две запятые дальше тела цикла, там работать должно.
И по хорошему внутри тела цикла нельзя делать даже print (как имеющий побочный эффект в виде вывода байтов в поток вывода), там все вычисления не должны иметь побочных эффектов (т.е. не менять состояние всего компа кроме локальных переменных и объявленных в export глобальных).

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 18:01 
Dmitriy40 в сообщении #1719933 писал(а):
Next надо делать не совсем внутри parfor, а в

Вц имеете в виду, next(2) надо делать в обработчике ошибки, верно? Или в обработчике ошибок взводить флаг типа pass=0 и потом уже выкидываться к следующей цепочке по next(2) т.е. как-то так:
Код:
my(pass=1); // предполагаем что цепочка хорошая
iferr(
    parfor(... // начинаем параллельную проверку чисел в цепочке, с ловлей ошибки
        ,
          if(
              цепочка плохая
               ,
              error() // если какое-то число в цепочке не прошло, взводим юзерскую ошибку
             )
     )
    ,
    E // в Е запишется юзерская ошибка
    ,
    pass=0 // ловим ошибку, меняем флаг хорошей цепочки на плохую
    );
if(!pass,next(2)); // если эта цепочка плохая, переходим к следующей

 
 
 
 Re: Как писать быстрые программы
Сообщение11.03.2026, 21:05 
wrest в сообщении #1719943 писал(а):
т.е. как-то так:
У Вас нарушен формат parfor. И pass не нужен. Надо как-то так:
Код:
iferr(
  parfor(d=0,19,\\До следующей запятой всё выполняется параллельно
    my(nd);
    nd=numdiv(17^d+3); if(nd>30, error(d));\\Вычисление nd и проверка на отказ
    nd\\Тут обязательно без символа ;, это что передать как результат вычислений, если хочется что-то сделать с ним, иначе можно оставить пустым
  , r,
  print(r);\\Здесь можно что-то сделать с r (которое в данном примере равно nd) или оставить пустым, это выполняется НЕ параллельно
  )
, ERR,
  next;\\Что делать если произошла ошибка, в component(ERR,1) сидит вектор аргументов error(), можно в нём передать например в какой позиции обнаружили отказ (как в коде выше)
, errname(ERR)=="e_USER"\\В принципе эта строка и не обязательна, но так надёжнее
);


-- 11.03.2026, 21:07 --

Про next в parfor был не прав, надо делать в обрамляющем iferr.

 
 
 [ Сообщений: 870 ]  На страницу Пред.  1 ... 47, 48, 49, 50, 51, 52, 53 ... 58  След.


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