LINUX.ORG.RU

Ответ на: комментарий от cvs-255

А почему двумерный массив? Я когда писал умножение матриц, матрицы, развернутая в одномерный массив быстрее умножаются

Dantix ★★
()
Ответ на: комментарий от cvs-255

Что-то я не уловил смысла написания этого кода: обычный подсчет ссылок. Широко используется. Но, во первых, в С++ есть готовые механизмы для этого, во вторых, точно так же можно забыть сделать a->unlink(), в третих, простой a->m++ сделает утечку и т.д.

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

я ж про «всякие тормозящие», а не про яву. Хотя для всяких первых приближений всё катит, плюс все «всякие тормозящие» умеют FFI, причём особо одарённые из них и за памятью последят (при некоторых ограничениях).

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

Если все правильно сделать, то выразительность кода будет как в matlab/octave а производительность как в C.

Хотя внутри оно может выглядеть как brainfuck и сообщения об ошибках от компилятора будут такие же.

amaora ★★
()
Ответ на: комментарий от cvs-255

Для корректного написания free, когда на одну и ту же память ссылается много указателей

Согласен, но это единственное применение.

Когда куча промежуточных вычислений
вызываешь сборщик мусора

Это лишнее, проще указатель стека сдвинуть при возврате из промежуточных вычислений.
Опять же можно забыть поставить флаг, как «постоянный» и получить внезапный сегфолт.

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

a->m++

m - private.

управляется через link, который вызывается вначале работы с указателем и unlink в конце

обычный подсчет ссылок

+ сборщик мусора

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от qnikst

по теме, а почему для работы с матрицами сразу бы blas/lapack-atlas не использовать? и проблем с памятью не будет по сравнению с ними наколенная реализация тормозить будет не меньше, чем всякие явы по сравнению с наколенной реализацией.

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

Опять же можно забыть поставить флаг, как «постоянный» и получить внезапный сегфолт.

Возможно. Но отловить такое _намного_ проще.

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

твоя реализация не является автоматическим менеджером по управлению памятью, это просто helper для твоей задачи, причём не гарантирующий корректность программы.

qnikst ★★★★★
()
Ответ на: комментарий от cvs-255

Код ужасен. Во-первых, с матрицами так работать нельзя. Во-вторых, тебе что это link/unlink руками надо вызывать? Если да, то это может привести к утечкам. Чем тебе не угодил стандартный C++-way? То есть всё на стеке + местами shared_ptr ?

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

Это лишнее, проще указатель стека сдвинуть при возврате из промежуточных вычислений.

А вот это точно путь к сегфолту, если я правильно тебя понял

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от qnikst

и проблем с памятью не будет

Конечно не будет, так как blas не аллоцирует и не освобождает память. Кстати, приведенный выше код blas-uncompatible, поэтому если захочется сменить low-level backend для линейной алгебры, то придется переделывать всю программу.

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

То есть всё на стеке + местами shared_ptr ?

примерно так и есть. только вместо shared_ptr своя реализация. Пишется всего за пару часов, а не надо сторонние библиотеки использовать.

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

Но отловить такое _намного_ проще.

_Намного_ проще чем, что? ИМХО, такие игры со временем тестами ловиться куда хуже, чем обычные утечки.

Makefile
()
Ответ на: комментарий от cvs-255

Нет, у тебя не тоже самое. Ты руками дергаешь link/unlink, поэтому это ничем не лучше ручного управления.

Reset ★★★★★
()
Ответ на: комментарий от cvs-255

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

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

Во-вторых, тебе что это link/unlink руками надо вызывать?

во-первых, при выделении нового массива link автоматически срабатывает.

во-вторых, link вручную надо писать лишь тогда, когда ты копируешь указатель.

в-третьих, по-умолчанию массив помечается как временный. И живет до ближайшего вызова сборщика мусора. unlink же нужен для постоянных объектов, которых сравнительно немного и которые четко видны в алгоритме. Ну и для освобождения памяти, когда ясно, что больше с ней дела иметь не придется.

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

m - private.

Мне показалось, что:

	public:
		...
		double** m;
паблик. Это неважно на самом деле, если надо руками вызывать unlink(); Также, не для всего подходят такие простые решения. И да, чем не устроил shared_ptr()?

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

Если уж использовать менеджер то не проще ли использовать язык где менеджер уже есть?

НъТъ. В некоторых случаях хочется явно сказать «а-ну выкинули все, что в этом пуле» и получить немедленное освобождение всяческих ресурсов (открытых соединений, файлов и тд). А не дожидаться, пока ленивый gc дочухает, что $ресурс уже можно освобождать.

gods-little-toy ★★★
()
Ответ на: комментарий от cvs-255

Нет, у тебя не тоже самое. Ты руками дергаешь link/unlink, поэтому это ничем не лучше ручного управления.

Я сперва пробовал сделать с ручным вызовом new и delete.

Так вот, по сравнению с таким подходом, в моей задаче ручной вызов - это кошмар.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от DNA_Seq

А нафиг вообще в юниксах треды?

дынасик полез программировать, ооох. Как ты несколько ядер без тредов заюзаешь? Процессами, c обменом данными через сокет?

gods-little-toy ★★★
()
Ответ на: комментарий от bender

Ну, это такая палка о двух концах, нет ничего плохого, чтобы переопеределить арифметические операторы для сообственного числового типа например, но с другой стороны, как часто пишутся сообственные числовые типы?

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

Понял, что имелось ввиду.

Так вот, я не идиот, чтобы m++ писать.

Так же, как я не вызываю rm -rf /* из под рута.

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

det(sub(add(Mat1, mul(Mat2, Mat3)), mul(Mat4, Mat5)))
det(Mat1 + Mat2 * Mat3 - Mat4 * Mat5)

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

Правильный вариант такой.

double * mat1, * mat2, * mat3, * mat4, * mat5;
mat_mul(tmp1, mat2, mat3);
mat_sum(tmp2, mat2, mat3);
....

Ну ты понял. Память в моем случае reusable и ничего постоянно не создается/удаляется.

Reset ★★★★★
()
Ответ на: комментарий от cvs-255

new и delete.
это кошмар.

Потому что нечего в си++ ковыряться в куче.

Makefile
()
Ответ на: комментарий от cvs-255

во-вторых, link вручную надо писать лишь тогда, когда ты копируешь указатель

это неправильно

И живет до ближайшего вызова сборщика мусора.

Зачем тебе сборщик мусора? Что ты пишешь?

Reset ★★★★★
()
Ответ на: комментарий от gods-little-toy

Как ты несколько ядер без тредов заюзаешь? Процессами, c обменом данными через сокет?

А легко. И, кстати, не обязательно через сокет.

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

в том смысле что если он используется из 2ух потоков, то вызов ощистки из одного гробит всё, что в другом?

qnikst ★★★★★
()
Ответ на: комментарий от gods-little-toy

Таки в чем проблема? Не сокетами, конечно, а через шмем или юникс домайн сокет, вполне прилично выйдет.

Makefile
()
Ответ на: комментарий от cvs-255

Так вот, по сравнению с таким подходом, в моей задаче ручной вызов - это кошмар.

Ты должен хранить указатель на сущность внутри объекта, а сам объект использовать по значению, тогда при вызове конструкторов копирования link будет вызываться автоматом. Но вообще, я сильно подозреваю, что тебе ничего этого не нужно и вполне хватит обыкновенного vector < double > matrix(n*m);

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

Зачем тебе сборщик мусора? Что ты пишешь?

Я пишу например

M = M1 * M2 + M3;

Тогда M1*M2 создает матрицу, которая затем складывается с M3.

Но вызвать для нее unlink после подсчета я не могу, т.к. в явном виде ее не получаю.

Потому она создается как временная, а после расчета вызывается сборщик мусора, который очищает оставшееся неочищенным.

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

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

Так вот, я не идиот, чтобы m++ писать.

Так же, как я не вызываю rm -rf /* из под рута.

Никто не идиот, также и не писать delete/free(). Но программы почему-то текут, бывает. Мне кажется тут есть какая-то закономерность.

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

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

Вот эти подводные камни и устраняет описанный метод.

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

Ды делаешь неправильный костыль для неправильного подхода. Тебе не нужно писать M = M1 * M2 + M3 в C++. В C++ пиши всё как есть, наиболее оптимальным способом. А красивый код надо писать в dsl из которого уже генерить C++.

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

Да. Но тут и без потоков есть пространство для выстрела в ногу.

note173 ★★★★★
()
Ответ на: комментарий от cvs-255

А почему бы просто не использовать boost::shared_array или std::shared_ptr<T[]>?

P.S. А еще у вас в коде ошибки :)

qrck ★★
()
Ответ на: комментарий от cvs-255

Не устранят. Я написал over 9000 различных алгоритмов алгебры. Так вот, в 200% память под все матрицы и вектора можно выделить один раз в начале функции или даже программы, поэтому вся эта свистопляска просто не нужна.

Постоянное выделение/освобождение памяти в расчетных программах это всегда плохо. Работа с матрицей как с double **, а не double * тоже плохо. Выделение через new [], а удаление через delete (без []) чревато segfault'ами.

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

Тебе не нужно писать M = M1 * M2 + M3 в C++

У меня есть много формул на бумажке. Я хочу их понятно перенести на компьютер.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от Reset

Выделение через new [], а удаление через delete (без []) чревато segfault'ами.

Это пишется в одном единственном месте. Его отладить вполне возможно.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от Makefile

С чего ты вообще взял, что тут будет утечка, или что нужно что-то освобождать?

С того, что матрица, получаемая в результате M1*M2 остается не освобожденной, т.к. для нее не делается unlink.

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

Переноси. Вот, например, кусок моего кода. Все понятно. И никаких переаллокаций нет.

        // w1/tau - 0.5 (1-theta)sigma(w1-w2) + mu(1-theta)(\Delta w1)
        vec_sum1 (&FC[0], &w1[0], &w2[0],
                  -0.5 * (1.0 - theta_) * sigma_, 0.5 * (1.0 - theta_) * sigma_, sz);
        vec_sum1 (&FC[0], &FC[0], &dw1[0], 1.0, mu_ * (1.0 - theta_), sz);
        vec_sum1 (&FC[0], &FC[0], &w1[0], 1.0, 1.0 / tau_, sz);

        // w2/tau - 0.5 (1-theta)sigma (w1 + w2) + (1-theta) mu \Delta w2 -
        // - alpha^2 u2/tau - alpha^2 (1-theta) mu1 w2 + alpha^2 sigma1 (1-theta) u2
        vec_sum1 (&GC[0], &w1[0], &w2[0],
                  -0.5 * (1.0 - theta_) * sigma_, -0.5 * (1.0 - theta_) * sigma_, sz);
        vec_sum1 (&GC[0], &GC[0], &dw2[0], 1.0, mu_ * (1.0 - theta_), sz);
        vec_sum1 (&GC[0], &GC[0], &w2[0], 1.0, 1.0 / tau_, sz);
        vec_sum1 (&GC[0], &GC[0], &u2[0], 1.0, -alpha_ * alpha_ / tau_, sz);
        vec_sum1 (&GC[0], &GC[0], &w2[0], 1.0, -alpha_ * alpha_ * mu1_ * (1 - theta_), sz);
        vec_sum1 (&GC[0], &GC[0], &u2[0], 1.0, alpha_ * alpha_ * sigma1_ * (1 - theta_), sz);
Reset ★★★★★
()
Ответ на: комментарий от Reset

Вот, например, кусок моего кода. Все понятно

...тебе

tailgunner ★★★★★
()
Ответ на: комментарий от cvs-255

Расскажи сколько временных объектов ты создашь/удалишь в этом месте

// w2/tau - 0.5 (1-theta)sigma (w1 + w2) + (1-theta) mu \Delta w2 -
        // - alpha^2 u2/tau - alpha^2 (1-theta) mu1 w2 + alpha^2 sigma1 (1-theta) u2

Reset ★★★★★
()
Ответ на: комментарий от cvs-255

С того, что матрица, получаемая в результате M1*M2 остается не освобожденной, т.к. для нее не делается unlink.

Не понимаю, если возвращается указатель на новую матрицу, то как складывается указатель с экземпляром класса? А если, возвращается копия экземпляра класса, то зачем ее освобождать (она сама освободиться же)? Ты ведь не переопределял операторы еще и для указателей на матрицы, я надеюсь?

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

А если, возвращается копия экземпляра класса, то зачем ее освобождать (она сама освободиться же)?

Возвращается элемент класса, содержащий указатель на матрицу.

А деструктор класса не должен очищать эту матрицу, т.к. может быть кто-то другой тоже использует этот указатель.

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