суббота, 20 февраля 2010 г.

Переопределим printf

Иногда бывает так, что printf ничего не выводит. Видимо, это из-за того, что она пишет в буфер, который по каким-то причинам не вываливает содержимое в stdout. Чтобы принудительно очистить это буфер используется fflush(stdout).

Логично переопределить printf как printf + fflush. Сложность в том, что у printf переменное число аргументов. если написать
#define printf(A) printf(A); fflush(stdout);
а потом задать строку форматирования с несколькими аргументами, компилятор ругнется, что-де слишком много параметров у макроса printf(A).

Решается это так (нашел в интернете)
#define printf(A) printf A; fflush(stdout);
printf(("t%d: RRJ in %d\n",TRED, t1));

Тут важно, что вызывать printf надо с ДВОЙНЫМИ скобками.

вторник, 16 февраля 2010 г.

ILU предобуславливатели.

ILU = incomplete LU preconditioner (оказывается, бывают и postconditioner-ы).

Неплохая дока по предобуславливателям этого класса - здесь.

Коротко:

1. incomplete - в смысле, произведение LU приблизительно равно матрице системы A. В отличие от обычного LU разложения, где A = LU.

LU - разложение -- хорошая штука, но если матрица A - разреженная, хранится в соответствующем формате, то хотелось бы, чтоб и произведение LU было бы разреженным. Т.е., мы раскладываем A в LU и начинаем выкидывать в L и U элементы в соответствие с некоторой стратегией. Равенство A = LU становится приближенным. Самый радикальный вариант - оставлять в LU элементы только в тех позициях (i,j), для которых a_ij не равен нулю (получим ILU(0)).

2. Предобусловленная система выглядит так: U^-1 L ^-1 A x= U^-1 L ^-1 b.

3. ILU(s). s - число уровней заполнения (levels of fill). Про ILU(0) см. в п. 1. А что такое уровни заполнения? Опять обратимся к LU-факторизации. Всем позициям, в которых a_ij не равен нулю, приписывается уровень нуль. Они считаются допустимыми. Вообще, допустимыми будут позиции с уровнем не больше s. Если позиция (при LU-факторизации) порождена двумя разрешенными позициями, то ей присваивается следующий уровень.

Прочитал я об этом в начале этой статьи (pdf).

4. MILU - modified ILU. Если в ILU стараются сохранить узор (zero pattern) A, т.е. {если a_ij<>0 => LU_ij = a_ij}, то в MILU это правило для i = j заменяют таким: {rowsum(LU) = rowsum(A)}

Бррр...

вторник, 9 февраля 2010 г.

Проверка существования файла в Unix shell

Есть вот такая команда Linux:
test -e filename - проверить, что файл filename существует ;
test -d filename- проверить, что файл filename существует и является директорией
(и куча других опций). На экран ничего не выводит, возвращает 1 или 0 если файл существует или не существует. Поэтому использовать лучше в скриптах. Например, если мы хотим удалить файл, надо сначала проверить его наличие, иначе rm выдаст ошибку, и скрипт дальше не будет исполняться.

Приведу кусочек makefile-a, где a)используется test : б) показан условный оператор shell:

if (test -f /usr/lib/libblas.a);\
then ($(FC) $(FFLAGS) -o driver driver.o splib.a -lblas);\
else ($(FC) $(FFLAGS) -o driver driver.o splib.a blas/localblas.a);\
fi

Здесь мы проверяем - есть ли в каталоге /usr/lib/ библиотека blas. Если да - линкуем с ней, иначе с blas-ом из директории ./blas.

четверг, 4 февраля 2010 г.

Работа с отладчиком dbx

Сказал бы мне кто-нибудь неделю назад, что буду дебужить в консоли - не поверил бы... "Мама это небыль, мама это не со мной".

Распишу по шагам, как работать с AIX-вским dbx. Обычный линуксовый gdb имеет свои особенности, dbx как-то поудобнее даже.

Итак - откомпиляли все сорсы (foo.c, stupid.c) с ключом -g. Получили бинарник (stupid).

1. Теперь запускаем dbx, грузим наш бинарник в него:
dbx stupid

Если хотим, чтоб отладчик искал сорсы в директории ./src, пишем:
dbx -I ./src stupid

2. Перед запуском отлаживаемой программы можно поставить брейкпоинты и задать способ трассировки (т.е., когда нужно будет выводить строки выполняемого кода).

поставить брякпоинт в файле foo.c на строке 9:
stop at "foo.c" : 9
[Набирать строчку надо без исправлений, без BackSpace, иначе отладчик говорит об ошибках синтаксиса]

поставить брякпоинт на функции foo:
stop in foo
(брякнется на первом выполняемом выражении).

Теперь трассировка:
  1. Трассировать каждый вызов printf :

    trace printf
  2. Трассировать каждое выполнение строки 22 в hello.c :

    trace "hello.c":22
  3. Трассировать изменение переменной x в процедуре main :

    trace x in main
  4. Трассировать данные по адресу 0x2004000:

    set $A=0x2004000
    trace $A
3. Запуск программы на выполнение (отладку) : r
если программе нужны флаги (например, -da), пишем r -da

4. После остановки на брякпоинте:
можно вывести значение одной переменной: print x
или всех переменных, которые видны из данного куска кода (текущей процедуры):
dump.
Кроме того, можно вывести стек вызова процедур: where.

5. Выход из программы - quit

среда, 3 февраля 2010 г.

Консольные отладчики gdb и dbx

Ну, вы знаете : Linux way - это консоль. Все в консоли, и отладка тоже. Очень необычно это для привыкших к Visual Studio, но со временем привыкаешь и начинаешь чувствовать себя хакером а-ля Касперски.

Отладчик gdb есть, похоже, во всех никсах. А в IBM-овской AIX есть еще свой - dbx. Так вот,
судя по хелпу, с их помощью можно выделывать весьма занятные фокусы. Скажем, менять значения переменных на ходу из отладчика, делать всевозможные дампы (например, можно сказать dump - и вам вывалят все переменные контекста), даже можно как-то двигать функции по стеку вызова вниз-вверх.

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

Мануал по dbx: здесь.

Пути для поиска файлов в Linux

Как известно, в Винде есть переменная окружения Path, где прописаны директории, в которых система ищет всякие хедэры, библиотеки и т.д. В Linux переменная , где хранятся с путями поиска подгружаемых библиотек, называется LD_LIBRARY_PATH. Изменять ее надо следующим образом (добавим еще одну директорию в список):
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"new_dir_name"

Также как и PATH, эта переменная скидывается при перезапуске системы :(

Кроме директорий из LD_LIBRARY_PATH, Linux всегда ищет библиотеки .so в /lib и /usr/lib