LINUX.ORG.RU

управление gc в common lisp в критичных местах


0

0

есть алгоритм с ростом по экспоненте, при определённых входных данных памяти не хватает(к примеру входные данные от 0 до 30, от 25 уже не хватает). алгоритм итеративный. хочу узнать, можно ли уменьшить критичный интервал, за счёт вызова gc вручную перед каждой новой итерацией или это и так делается? внутри главной итерации перед самыми затратными кусками кода, не нуждающимися в некоторых выделенных до этого дынных?

Ответ на: комментарий от Love5an

Прикольная аватара:)
Представляю тебя на ней и себя через пару лет:)

anonymous
()

Вызов gc — это trivial-garbage:gc (который для sbcl эквивалентен sb-ext:gc). А вообще, самое лучшее — это искать места, где выделяется лишняя память, и убирать выделение памяти.

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

Ну в R например расстановка gc() вполне облегчала работу, иначе складывалась ситуация когда OS начинала свопить «незная» ничего о том что вот сейчас придет gc().

Это получается что gc() должен ориентироваться на попытки OS начать свопить именно процесс под его управлением и сначала делать попытку освободить память «до того как». Может в лиспе gc() именно так и ведет себя?

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

По моим наблюдениям, размер потребляемой SBCL памяти зависит от наличия доступной в системе, т.е. он ведёт себя достаточно интеректуально, учитывает возможность свопа и пытается его минимизировать.

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

Логично. Java VM тоже вибирает параметры б/м интеллектуально, а из коммандной строки можно указать прямо, сколько памяти поедать максимум. Правда для SBCL такого я не нашел.

Можно зарезать через setrlimit на худой конец.

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

У меня на linux нет. Это важный параметр, например, для vps на базе debian, где SBCL по-умолчанию ведёт себя довольно безобразно, это позволяет умерить начальные аппетиты системы. Правда, если указать слишком мало, то может вообще не стартануть :)

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

>Просто не надо пользоваться подобными алгоритмами.

Вы таки не поверите, но ВНЕЗАПНО не все задачи можно решить полиномиальным алгоритмом.

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

Вы, видимо, тоже не поверите, но ВООБЩЕ не все задачи можно решить. Если системе не хватает памяти, то надо что-то менять, а не пытаться продлить конвульсии.

archimag ★★★
()

0 юзать sb-sprof и искать — кто щедрый

1 Думать, как сделать не таким щедрым

Ссылки на закуску: http://john.freml.in/sbcl-optimise-gc

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

>Вы, видимо, тоже не поверите, но ВООБЩЕ не все задачи можно решить. Если системе не хватает памяти, то надо что-то менять, а не пытаться продлить конвульсии.

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

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

ну надо еще сказать что код не видел никто... велика вероятность что надо менять не алгоритм, а реализацию... может там рекурсий тысячи, не хвостовых :)

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

реализация итеративна и не содержит ни одной не хвостовой рекурсии, сам алгоритм можно сравнить с
вход - (1 2 3)
действия над -
(1 2) (1 3) (2 3) (2 4) (3 4)
(1 2 3) (1 2 4) ...

предложение менять алгоритм - показуха

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

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от Waterlaz

Если для алгоритма не хватает памяти, то плохой, ибо его нельзя запустить. Либо железо плохое. Как посмотреть. А в чём состоит ваша позиция по этому вопросу?

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

>Если для алгоритма не хватает памяти, то плохой, ибо его нельзя запустить. Либо железо плохое. Как посмотреть. А в чём состоит ваша позиция по этому вопросу?

Не принимай мои комментарии за грубость. Я лишь хотел сказать, что автор то не по алгоритму просил помощь.

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

> Это получается что gc() должен ориентироваться на попытки OS начать свопить именно процесс под его управлением и сначала делать попытку освободить память «до того как».

Именно к этому выводу пришли однажды Уолтер Брайт и Андрей Александреску. Ждём сборщика мусора в ядре.

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

>> Это получается что gc() должен ориентироваться на попытки OS начать свопить именно процесс под его управлением и сначала делать попытку освободить память «до того как».

Именно к этому выводу пришли однажды Уолтер Брайт и Андрей Александреску. Ждём сборщика мусора в ядре.

Ну, н хаскеле модули ядра уже пишут, путём запихивания ентого хаскиля в ядро, с его gc. Так что дело за малым — не sbcl в виде модуля ядра сделать, так ecl. Ядрож монолитное, ему всё равно.

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

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

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

(defun test ()
  (labels ((iter (x)
	     (let ((y (+ x 1)))
	       (if (> y 10)
		   y
		   (iter y)))))
    (iter 0)))

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

что такое dynamic-extent

На моём уровне понимания, это значит, что объекты, которые ты будешь создавать и помещать в эту переменную, будут размещены на стеке. Соответственно, если ты создаёшь список функцией list, то он целиком будет размещён на стеке, а не только его первый cons.

(defun f ()
  (let ((x (list '#:a 'bbb 3)))
    (declare (dynamic-extent x))
    (print (length x)) ; правильно - используем значение, 
 ; выделенное на стеке, в вычислениях
    (print (last x)) 
 ; сомнительно, т.к. нет гарантии, что string
 ; не создаст долгоживущих ссылок на свой аргумент 
 ; (например, для передачи копии потока ББ)
    (last x) ; неправильно, потому что
 ; возвращаем из функции значение, выделенное на стеке
    ))

В общем-то, вполне аналогично локальным переменным в C.

Первый нюанс, как я понимаю, состоит в том, что переменная с dynamic-extent прямо или косвенно ссылаться на другие объекты, выделенные в куче или выше по стеку. Т.е., мы имеем право сослаться на символ bbb, выделенный в куче и принадлежащий пространству имён.

Здесь для меня самого непонятно, будет ли символ '#:a выделен на стеке в реализациях лиспа. По идее, декларация dynamic-extent позволяет доказать, что символ можно положить на стек. Символ #:a заведомо является «иначе недоступной» частью значения переменной x, т.к. это - бездомный символ. Но вот догадаются ли до этого реализации?

Впрочем, это нетрудно проверить с помощью time. Для этого нужно, скорее всего, поместить определение функции в файл и поставить в его начале (proclaim (optimize speed)) или (proclaim (optimize (speed 3) (debug 0) (safety 0))) а файл скомпилировать перед загрузкой.

Если вызовы (time (f)) для (list nil 'bbb 3) и (list '#:a 'bbb 3) покажут одинаковые результаты по выделению памяти, а то же самое, но без dynamic-extent - другие результаты, то значит:

1. декларация dynamic-extent используется 2. символ '#:a выделяется на стеке и поэтому не создаёт мусора.

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

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

а на стек память выделяется заранее или он только ограничивается свободной ОЗУ? если заранее, то почему бы только после заполнения кучи не класть локальные переменные полностью на стек?

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

Однако, стек заканчивается намного раньше кучи

ой, не обратил внимания, видимо память выделяется заранее. Но второй вопрос всё ещё в силе :)

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