green_fr: (Default)
В MatLab есть функция isa(object, className), которая проверяет, является ли данный объект «совместимым» с указанным классом (либо объект самого класса, либо объект одного из наследующих классов). Оно само по себе плохо, иметь код с такими проверками, но так уж получилось, у нас такое есть. Например, когда в одном файле хранятся объекты разного типа (скажем, актив и пассив), а я хочу прочитать их и сделать какую-то операцию только с объектами определённого типа (скажем, только с активом, посчитать общую сумму). Я мог бы базироваться на имени переменных, но это для меня ещё хуже, чем проверять тип данных.

Так вот, функция isa. Проблема для меня в слове «name» — я не люблю использование строк в этом контексте. Например, если я поменяю название класса, я хотел бы, чтобы функция isa не просто отвечала «ой, нет», а выдавала ошибку «не знаю такого класса» (причём лучше даже ещё на этапе компиляции). Ну и всякие там утилиты рефакторинга (предположим, они когда-нибудь появятся и для MatLab) лучше бы работали, если бы это была не просто строка, а прямая отсылка к классу.

При этом за последние годы в MatLab дописали много связанного с reflexion, полез в RTFM. Вижу, что есть класс meta.class, у которого есть свойство Name — это же то, что мне надо! Осталось понять, как получить объект этого класса, соответствующий нужному мне классу. Откопал, что есть какой-то убогий синтаксис ?MyClass. Убогость его в том, что эта конструкция вырывается из общей структуры программы на MatLab — что за вопросительный знак? Почему это нельзя было хотя бы оформить в виде свойства или метода (как это сделали в java)? И таки да, за счёт этой убогости я не могу прицепить эту инструкцию к последующим вызовам. То есть не работает не только двусмысленный ?MyClass.Name, но и очевидный (?MyClass).Name. Только через временную переменную: сначала meta = ?MyClass, а уже потом meta.Name.

Пишу в support. Пускай, если не покажут как сделать, то хотя бы запишут запрос для следующей версии.

Первый ответ. Да, лучше всего использовать временную переменную. Но можно и без неё. Объект класса meta.class можно получить не только через класс, но и через объект этого класса. См. метод class(myObject). А если у вас нет под рукой объекта нужного вам класса (нет, у меня в этот момент его как раз нет), то вы можете попытаться схитрить и написать class(MyClass()) - при условии, что у вашего класса есть пустой конструктор. Нет, и пустого конструктора у меня тоже нет. Более того, у меня куча абстрактных классов, так что даже создать пустой конструктор исключительно для этого использования — это не вариант.

Второй ответ. Вы знаете, мы тут посоветовались с разработчиками, и к вашей проблеме можно подойти с другой стороны. Вы уже знаете, как получить meta.class нужного вам класса: ?MyClass. И у вас есть объект, для которого вы тоже можете получить meta.class его класса: class(myObject). Осталось только сравнить эти два мета-класса, а для этого у нас есть операторы «>=» и «<=»! Стоп, думаю. Они мне что, предлагают тупо проверять на идентичность два объекта класса meta.class? А если у меня класс объекта наследует от проверяемого класса: это совместимые, но разные классы, объекты их meta.class будут разными.

Прежде чем выругаться «что вы меня, за идиота держите?!», проверяю — а оно работает. Реально, я могу арифметически сравнивать два объекта meta.class, и наследующий класс строго меньше наследуемого, а наследуемый строго больше наследующего. При этом, если сравнивать два класса из разных ветвей, то любое сравнение (больше, меньше, равно) будет выдавать негативный результат.

Пишу в ответ: хмм... спасибо, это, конечно, работает, но выглядит каким-то безумным хаком. Это хотя бы где-то документировано? Или просто «так получилось»? Основывать свой функционал на таких соплях, которые, возможно, уже в следующей версии перестанут работать, лично мне страшно. Приходит ответ: ну что вы, конечно это фича!

Тикет закрыли. Но учитывая, что изначально я стремился к большей лёгкости управления кодом (представил себе, как я буду объяснять эту строчку коллегам...), применять новые знания я не стал :-)
green_fr: (Default)
На новый год [livejournal.com profile] sasmok подарил мне календарь-головоломку. Нужно уложить вот эти 8 деталей вот в эту форму, чтобы в оставшихся клеточках была видна текущая дата. Справа — решение для сегодняшней даты.



Какое-то время я пытался решить для 1 января — нужно же всё делать по порядку! Потом для текущей даты — нужно же сделать хотя бы что-то! Затем просто складывал детали в надежде, что когда-нибудь они улягутся, и записывал получавшиеся даты впрок. Ну а потом вспомнил про MatLab.
Read more... )
green_fr: (Default)
Выходит новая версия MatLab, я, как обычно, читаю release notes.

Вводятся новые функции: sinpi и cospi. Compute the sine and cosine of multiples of π. Первая реакция, конечно, ржать — мега-полезные функции. Потом понимаешь, что multiples of π — это не обящательно «целое число π». Более того, документация показывает разницу округления: sin(pi) действительно выдаёт 1e-16, тогда как sinpi(1) строго равен 0. Потом начинаешь задумываться о вменяемости алгоритмов, чувствительных к таким округлениям.

В рубрике see also упоминают функцию sind, считающую синус аргумента в градусах (ичсх, функции cosd нет). С документацией примерно в том же духе: sind(180) выдаёт ровно 0, потому как никакого округления.
green_fr: (Default)
На работе надумали обзавестись серьёзным production для проекта, написанного на MatLab.

Как говорят на anekdot.ru, преамбула. Мы когда-то давно говорили с MathWorks по несколько иному поводу — у нас были сомнения в производительности системы, они предложили аудит нашего кода, мы с удовольствием согласились. Ребята втроём копали код несколько дней, сгенерировали кучу слайдов для презентации, которая сводилась к двум пунктам:
1. Ваш код написан идеально, не к чему придраться!
2. Мы можем вам продать сервер за какие-то шестизначные суммы в год, летать будет всё.

Первый пункт лично мне понравился, но оставались какие-то сомнения в его искренности. Через некоторое время у меня дошли руки просмотреть profile проекта, перечитать код модуля, который жрал 90% общего времени (в качестве отмазки себя и своих коллег скажу, что он таки был написан IT-консультантом, настоящим профессионалом своего дела, за какие-то космические деньги в час), выкинул оттуда все лишние строчки (только то, что считается по два раза, и то, что считается впустую — никакой алгоритмической оптимизации), и код стал работать вчетверо быстрее.

После чего сомнения появились и во второй строчке презентации MathWorks (дети! никогда не обманывайте! особенно там, где вас можно легко поймать...) — так ли нам нужен их сервер, если мы можем скопилировать проект и распихать его по уже имеющимся серверам в виде простых exe-шников?


Перехожу ко вчерашней истории. Погоняли мы проект на Windows-машине, хоть на физической, хоть на виртуальной. По этому поводу удивительное дело — у нас IT-дирекция перешла недавно на какую-то более свежую версию виртуализации, и вместо x4 к времени рассчётов, как было раньше, виртуализация даёт всего +10%. Очень хорошо, но мы решили проверить и виртуальные Unix-машины. И тут начался эпос.

1. Компилятор MatLab компилирует только под ту платформу, где он сам находится. При том, что для скомпилированного кода ставится «Matlab runtime environment» на гигабайт, то есть я ожидал компиляции по типу java — в некоторый псевдо-код, единый для всех платформ. Но нет. Я несколько раз переспрашивал, прежде чем поверил. В счастью, «платформа» — это одна из трёх групп: Windows, Mac, Unix.

2. У нас нет клиентских Unix-машин. В смысле простого доступа к ним (я не могу ни «подключиться к экрану», ни зайти по telnet — это отдельная сетка, мне туда входа нет. Договорились, что я подъеду в Orléans, где сидят наши администраторы. По этому поводу — карикатурная ситуация с бородатыми админами в майках и с пивом осталась, только мальчики успели подрасти и поседеть/полысеть, но атмосфера всё та же.

3. У нас нет никакого графического интерфейса на Unix. По этому поводу MathWorks выдал прекрасный термин (наверное, распространённый, я просто давно не общался на эти темы): headless installation. Да, MatLab можно поставить без GUI, только с командной строкой.

4. Стандартный вариант установки: скачиваем «маленький» инсталлятор (120 MB), вводим все идентификаторы, и он скачивает всё необходимое для установки именно того, что ты купил. Очевидно, что этот инсталлятор графический, для нас не подходит. Ок, говорят MathWorks (в какой-то момент они меня начали по голосу узнавать, я им звонил раз 10 вчера), вы можете скачать два iso-образа со всеми продуктами, в момент инсталляции поставится то, что вам нужно. По этому поводу я не премину потоптаться по компетентности наших коллег из MathWorks. Говорят дословно: скачайте iso-образы и разархивируйте их в одну папку. Что значит, «разарзивируйте», в некотором ошалении спрашиваю я? Да, говорят, это то же самое, что zip, он просто называется iso :-)

5. Скачали образы, 11 GB. Сидящий рядом со мной администратор Unix’а начинает нервничать, потому что у него на машине свободного места не так много, и он не собирался сегодня пересматривать всю свою файловую систему. Начали ставить, места предсказуемо не хватает. Попытался стереть откровенно ненужные файлы (всё, что начинается с Simulink — это другой продукт MathWorks, мы его не покупали), но установщику зачем-то нужны все эти файлы. Я вспомнил молодость, жонглирование файлами на дискетах без жёского диска — красиво, но нет, тоже не получилось. С матюками админ полез добавлять ещё одну файловую систему.

6. Ещё одно погружение в детство — для установки нужно отредактировать файл параметров. Очевидно запускаем vi — и руки мои всё ещё помнят, как в нём работать! В этот момент я, по-моему, сильно вырос в глазах всех администраторов. До этого я был для них очередным «представителем клиента», человеком, который должен путать слова «монитор» и «компьютер».

7. Аутентификация MatLab’а проходит через так называемый license server. У нас было много вопросов по этому поводу: моя лицензия привязана к моему Windows-account, как объяснить серверу, что я из-под Unix — это тот же самый я? Попытались вообразить разные варианты аутентификации, потом всё-таки позвонили MathWorks — спокойно, говорят. Мы проверяем только имя пользователя. Чисто как строку. Хозяйке на заметку: для того, чтобы использовать зарегистрированный на кого-то другого MatLab, достаточно создать локальную учётную запись с тем же именем.

8. С горем пополам поставили, скомпилировали, запустили — не работает. Но это уже понятно: у нас весь код с анти-слэшами, а для Unix’а слэши нужны прямые. MatLab даже предлагает мега-функцию filesep, которая возвращает «\» или «/» в зависимости от платформы. На этом мы с админами расстались, договорившись, что я сегодня перепишу всё через эту функцию.

9. Приехав сегодня на работу, я увидел, что мы используем ещё и system для запуска команд DOS (тоже всё работа с файлами) — понятно, что можно написать везде if и продублировать на Unix, но как мы всё это будем тестрировать без доступа к машинам? Плюс, у нас есть работа с Excel — опять же, MathWorks божится, что все его функции используют MS Office API только для скорости, а если Офиса нет — то они и своими средствами обходятся, но как-то даже и пробовать расхотелось. Спасибо за творчески проведённый день, но мы пока что останемся на той же платформе.
green_fr: (Default)
После вопроса про миллиард секунд разговорился с коллегами. Полезли проверять, чему соответствует дата 0 в наших системах.

Про Excel я помнил, что там это 00/01/1900, но при этом мне почему-то в голову не приходило проверить, чему соответствует дата −1. Оказалось, ничему — в Excel невозможно поставить дату до начала 1900 года.
(если я правильно помню, Excel под Mac долгое время ставил нулевую дату на 00/01/1904, поэтому в современных версиях Excel есь возможность выбора базы для дат — я на эти грабли уже наступал, прелесть)

В Matlab нулевая дата тоже приходится на нулевое января, только и год там нулевой: 00/01/0000. Зато — прогресс! — он понимает отрицательные числа. И дата −1 попадает на 30 декабря 9999 года. Почему 30 декабря, понятно — чтобы через 2 дня было 1 января, а что там между ними — 31 декабря или 0 января, — это уже детали. И почему 9999 года тоже, наверное, понятно — в какой-нибудь первой версии MatLab вывод даты был предусмотрен только в рамках 4 цифр: проблему 2000 года решили, а даты до нашей эры никого никогда не будут интересовать.
green_fr: (Default)
Продолжаем фанфик курса программирования в УБЗ. [livejournal.com profile] catpad выкатил игру «Жизнь» одной строчкой на APL:



Потратив некоторое время на поднятие челюсти восхищение чистым разумом, я задумался, как всё это выглядело бы на MatLab. На самом деле, отличия не сильные. Опять же, сохраняя обозначения исходного курса, разобьём на блоки:

M = zeros(5);
M(3, 2 : 4) = 1;
V = {-1, 1};
B2 = cellfun(@circshift, repmat({M}, 1, 4), [V, V], 'UniformOutput', false);
B3 = cellfun(@circshift, B2, [V, fliplr(V)], repmat({2}, 1, 4), 'UniformOutput', false);
B4 = cellfun(@circshift, repmat({M}, 1, 2), V, 'UniformOutput', false);
B5 = cellfun(@circshift, repmat({M}, 1, 2), V, repmat({2}, 1, 2), 'UniformOutput', false);
B6 = sum(reshape(cell2mat(B3), [size(B3{1}), numel(B3)]), 3) + plus(B4{:}) + plus(B5{:});
B7 = B6 == 2;
B8 = B7 & M;
B9 = B6 == 3;
B10 = B8 | B9

Буковок несомненно больше. В первую очередь из-за параметра UniformOutput для cellfun: в MatLab «матрица, содержащая матрицу» — это cell array, и для него операции несколько отличаются от операций с матрицами.

Вторая неприятность заключается в том, что я не умею складывать элементы cell array. Для B4 и B5 всё просто — можно использовать sum, принимающий не более двух элементов, а там их как раз два. Но вот для B3 случается неприятность — я её обхожу переформатированием cell array -> matrix 5×20 -> matrix 5×5x4, которую затем суммирую вдоль третьего измерения. Если кто-нибудь подскажет более элегантный способ суммирования, я буду очень ему крайне признателен.

Сборка результата не отличается практически ничем. Отмечу отсутствие «;» в строке с B10, заставляющее MatLab вывести на экран результат этой операции. Лично я (равно как и встроенный анализ синтаксиса mlint) считаю это крайне порочной практикой и обычно использую для вывода на экран disp.

Теоретически это можно даже собрать в одну строчку, но здесь возникает ещё одна проблема — MatLab не позволяет написать (a + b)(:) (применить оператор индексации не к переменной, а к результату операции). Это обходится через subsref, который, впрочем, я тоже считаю плохой практикой.

Не говоря уже о засовывании всего этого в строку и вызове eval — от одного вида этой функции меня бросает в дрожь, она официально забанена у нас на проекте. Поэтому нет, циклы Жизни можно, конечно, запихнуть в одну длинную строку, но этим я не буду заниматься даже ради фанфика!
green_fr: (Default)
Курс программирования на УБЗ. Глава 5. Часть 1. A Programming Language или Уроки Практической Магии.

Удивительно, но я не только не знал до сих пор APL, но и услышал о нём, мне кажется, впервые. Хотя, как можно было не выучить язык, на котором программа выглядит следующим образом:

(((1,A)/B)⌊1+⍴Y)[(⍴Y)↓(+\1,A←(1↓A)≠¯1↓A←A[B])[⍋B←⍋A←Y,X]]

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

1. «⍳x» — это, очевидно, «1 : x». Даже «⍳0» эквивалентно «1 : 0» в том смысле, что оба возвращают «ничто». От себя замечу, что в Матлабе не бывает просто «ничего», оно всегда размерное. Данное ничего имеет размерность 1×0, оно так и называется «1×0 empty double row vector». Для удобства пользователя есть отдельная функция empty, позволяющая создать пустоты разного размера, например, double.empty(0, 0, 1, 2) создаёт пустую матрицу 0×0×1×2.
2. «⍴» - это MatLab’овский repmat. Отличие от APL в том, что приходится явно указывать, сколько раз плодить исходную матрицу в каждом из измерений — поскольку просто «пустоты» не бывает.
3. Минимум и максимум, конечно же, пишутся min и max. Небольшое отличие от примера из первой главы APL в том, что они снова ищут минимумы и максимумы вдоль одного из измерений (по умолчанию первого, но, к сожалению, есть нюансы). То есть, min возвращает матрицу той же размерности, что исходная, за исключением размерности, по которой проходил поиск, где размерность будет равняться 1. Т.о. min(0 : 1) вернёт ничего размерности 1×0.
4. Но нельзя же работать без самого большого и самого маленького чисел, для них в MatLab есть специальные литеры: Inf и -Inf. А в добавок ещё и eps — это тоже «самое маленькое число», но в другом смысле: это самое близкое к нулю число, которое ещё отличается от нуля (на моей машине это 2,22e-16).
5. Унитарный вариант «⍴» — это буквальный аналог MatLab’овского size. Хотя нет, аналог не полный — из каких-то своих соображений size никогда не возвращает скаляр. Даже для скаляра он возвращает вектор из двух элементов — действительно, скаляр эквивалентен матрице 1×1. Но он же эквивалентен и матрице 1×1×1×1×1×1. Очевидно, на двух измерениях остановились в силу каких-то исторических причин (в языке полно рудиментов, когда первые два измерения трактуются отлично от следующих).

Конечно, редкая программа на MatLab помещается в одну строчку (у нас кода на 4MB), но это не мешает мне любить свою работу. Но клавиатура как в статье УБЗ мне не помешала бы :-)
green_fr: (Default)
Сходил к MathWorks, послушал пару часов, как правильно оптимизировать инвестиционные портфели. В качестве примера, как можно при этом использовать MatLab, рассказали о существовании разнообразных twitter’ов, транслирующих новости о тех или иных компаниях. И о существовании контор, собирающих и перепродающих такие твиты. А также о людях, пытающихся на основе этих твитов что-то вывести об описанных компаниях (звучит глупо, но в принципе вполне соответствует идее разумного рынка, оперирующего суммой подсознательных знаний всех его игроков).
Но самое смешное в реализации, конечно же. Лектор прочищает горло и с гордостью представляет нам лично им обученную систему, нейронную сеть, едва не искусственный интеллект. Программа, способная анализировать каждый твит, связанный с котируемой на бирже компанией, и выставлять твиту оценку: положительная (твит говорит о чём-то хорошем для компании => ждём повышения её акций), отрицательная (симметрично) или нейтральная (понять невозможно). Долго, говорит, писал. Запустил самообучение на суперкомпьютере, 8 часов. Да, говорит, система далека от совершенства, её ещё можно дорабатывать. Но уже сейчас! она способна!! с уверенностью правильно определить характер 33% анализируемых сообщений!!111

Не удержался, переспросил. Простите, говорю. Программа определяет, к какому из трёх классов принадлежит конкретное сообщение, и с вероятностью в 1/3 делает это правильно?
На следующей неделе иду на 3-дневный курс тех же людей на ту же тему. Срочно ищу себе кляп в рот.

MatLab.m

Jul. 8th, 2014 03:27 pm
green_fr: (Default)
Смог, наконец-то, скомпилировать программу, над которой мы работаем уже несколько лет (до сих пор пользовались только в режиме интерпретатора), и задался вопросом. MatLab — платная программа. Достаточно дорогая, особенно когда начинаешь докупать разные модули, да на много человек. При этом, MCR (run-time environnement) распространяется бесплатно. То есть, всё, за что мы доплачиваем, покупая MatLab — это IDE, т.к. работающие библиотеки со всеми функциями можно бесплатно скачать на сайте MathWorks. Вопрос — насколько сложно сделать этот IDE средствами того же MatLab? Или прикрутить какой-нибудь eclipse (который, к слову, на порядок круче стандартного IDE MatLab)?

P.S. Я знаю о существовании бесплатных аналогов, мне интересна исключительно их бизнес-модель. Наличие бесплатного JRE фактически сделало бесплатным распространение java (не будем, что было причиной чего), .NET тоже распространяется бесплатно. Почему у MatLab’а с той же моделью получается получать деньги за IDE?

Или я чего-то не понимаю?
green_fr: (Default)
Продолжаю копать недавний вопрос, довёл ситуацию до минимализма, и всё равно ничего не понимаю.

Есть некий скрипт, который выглядит примерно* так:
a = random(...);
b = random(...);
for i = 1 : 1000
    a = a + b;
end

1. Запускаю его на своём компе — память загружена на некотором уровне X, процессор загружен на 25% (у меня 4 ядра, MatLab крутится на одном из них), время работы цикла 19 секунд.
2. Запускаю два MatLab, на каждом из них запускаю ручками копию этого скрипта. Память загружена вдвое больше (логично), процессор загружен на 50% (логично), время работы цикла 34 секунды (я ждал, очевидно, 19 секунд).

В чём фишка? Единственное разумное объяснение — меня ограничивает скорость чтения / записи RAM. В это не хочется верить, и как минимум хочется поверить.

Откуда следующие вопросы:
1. Как получить максимальную скорость чтения / записи RAM? Измерить / посчитать по техническим характеристикам / запустить утилиту.
2. Как посмотреть реальную скорость работы с RAM? В идеале иметь такой монитор, как Task Manager, который рисовал бы график в реальном времени, чтобы на нём глазами увидеть потолок, об который стучится мой процесс. Наш IT выслушал, попробовал две какие-то стандартные у них утилиты и развёл руками. Hotline MatLab вообще вопроса не понял (провёл с ними час по телефону, зол неописуемо).
3. (в голову как-то не лезет, что программу тормозит RAM, с детства привыкли, что у него скорость, конечно, ограниченная, но это только в теории) Какие ещё есть варианты объяснения этого эффекта?


*Скрипт выглядит «примерно» так, т.к. MatLab в принципе иногда работает с несколькими ядрами процессора. Например, простую операцию a + b он легко раскидывает на несколько ядер. А вот bsxfun(@plus, a, b), позволяющую складывать матрицы разного размера, уже не раскидывает. Поэтому для простоты я написал +, но на самом деле там bsxfun.
green_fr: (Default)
Пытаюсь закрутить нашу программу чуть побыстрее. Взяли потестировать PCT, который, теоретически, с минимальными исправлениями кода позволяет раскидывать расчёты на разные процессоры, а то и компы. Например, говорят, если у вас есть цикл for, все итерации которого совершено независимы, то вы можете просто заменить ключевое слово for на parfor, и PCT сам разберётся, какую итерацию на какой процессор посылать, как собрать потом результаты и т.п.

Начал тестировать. Вот есть у меня некая процедура doSomeWork(), которая читает какой-то файл с диска, что-то там считает и пишет результат на диск же. Время её работы засёк — 664 секунды. Написал цикл из одной итерации:
for i = 1 : 1
doSomeWork();
end
Проверил, всё ещё 664 секунды.
Запустил PCT, поменял for на parfor — 734 секунды.

Ненормально. Попытался понять, что происходит. MatLab при запуске PCT создаёт дополнительные процессы MatLab, то есть в моём случае крутилось два процесса: один — тот, что исполнял скрипт до parfor, а потом работал диспетчером, и второй — который отрабатывал единственную итерацию моего цикла. Теоретически, есть какая-то потеря времени для передачи данных от одного потока к другому. Но у меня нарочно сделано так, чтобы не было видно вообще ни одной лишней переменной. Теоретически, нужно скопировать код (я не знаю, могут ли разные процессы делить один код, не думаю), но всё равно ведь не на 70 секунд работы!

Поменял цикл до 2, запустил снова. Вижу, как у меня крутится 3 MatLab'а — 2 сожрали по куче памяти (каждый процесс кушает где-то 3GB) и по одному ядру процессора, а третий почти ничего памяти и на нуле процессор, он ждёт.

Время работы — 931 секунда. Оппаньки! Опять же, я понимаю, что у меня есть какой-то код, который не параллелится (чтение данных с диска, запись результатов), но его там с гулькин нос, на пару секунд работы (я проверял). А кроме чтения диска я не вижу ничего — ни сеть не используется, ни ещё какие другие внешние устройства. Куда время потерялось?

С тремя итерациями время ускакало вообще до 1223 секунд, смысл распараллеливать постепенно пропадает.

Проверил, что у меня хватает памяти (не начало ещё свопить) — только сегодня поставили 16GB, а даже с тремя считающими MatLab’ами используется до 11GB. Проверил, что параллельно на этом компе ничего ресурсоёмкого нет (только ЖЖ).

Какие ещё есть варианты? Куда смотреть? А то официальный support откровенно косит под тупых (проблемы только у вас, а у нас вот только что один крупный клиент заказал ферму на 700 ядер, и всё работает!), не сложились у меня как-то с ними отношения...
green_fr: (Default)
Нашёл багу в MatLab — при определённых обстоятельствах они зачем-то вызывают функцию обработки спецсимволов URI, таким образом, если в названии папки есть «+», он заменяется на пробел, и ничего, конечно же, не работает — file not found.
Написал bug report, через какое-то время человек из службы поддержки понял ошибку и выдал прекрасное решение моей проблемы.
А вы переименуйте, говорит, папку, чтобы там плюсика не было.
Обязательно проверьте, исчезла ли ваша проблема, и напишите мне, чтобы я смог закрыть ваш bug report.

Думал было написать ему Are you serious?, но в итоге решил проигнорировать.
green_fr: (Default)
Кто-нибудь знает утилиту для форматирования кода MatLab?
А то MathWorks только пару версий назад додумались вставить функцию smart indent, до прочих прелестей руки у них не при моей жизни дойдут...

Как вариант — универсальная утилита форматирования программного кода, которую можно было бы настроить. Меня интересует indent после некоторого количества ключевых слов, возврат при некотором количестве закрывающих ключевых слов, и (главное) грамотно расставленные пробелы.

А то унаследовал какое-то огромное количество ну совершенно нечитаемого кода.
green_fr: (Default)
Пытаемся причесать немного нашу программу на MatLab’е, группируем написанные разными людьми скрипты в классы.
И вдруг замечаю, что функция, оформленная в виде метода, исполняется в разы медленнее... Один и тот же код (copy-paste), только данные не в глобальных переменных, а члены класса.

Позвонил в support, они мне говорят, что это не баг, это фича: доступ к переменным объекта занимает слегка больше времени, чем доступ к простым переменным. Пообещали передать разработчикам, но, судя по внутренней базе, разработчики не считают это поведение анормальным.

Оказалось, MatLab не помнит результатов проверок, которые он проводил только что. Например, в методе класса есть цикл, в цикле мы обращаемся к переменной класса (мой случай — к статической константе!). Так вот, он на каждой итерации будет проверять, существует ли такая переменная, не переопределена ли она дочерними классами, и какой у неё уровень доступа.

Написал «патч»: в начале каждого метода считываю константы в локальные переменные.
Одна из функций разогналась с 42 секунд до полутора.
Послал предложение усовершенствования в MathWorks, может премию вышлют :-)

Yearfrac

Apr. 6th, 2011 02:09 pm
green_fr: (Default)
В MatLab есть замечательная функция yearfrac, которая возвращает разницу между двумя датами, выраженную в годах. При этом у функции есть третий параметр, правило подсчёта разницы — в финансах регулярно используются довольно экзотические правила, рудименты докомпьютерной эпохи. Например, между 1 январём и 1 февралём может быть 1/12 года (правило 30/360), 31/365 (правило actual/365) или иногда 31/365, а иногда 31/366, в зависимости от високосности года (правило actual/actual). Правил несколько десятков, но в нормальных условиях всегда используется правило actual/actual, это значение параметра by default.

А только что я обнаружил ужасный баг в этой, казалось бы, простой функции. Если посчитать разницу между 01/01/2007 года и 01/01/2009 года (здесь и далее только actual/actual), то функция выдаёт значение 731/365. Между 01/01/2008 года и 01/01/2010 года — 731/366. И только между 01/01/2009 и 01/01/2011 получаем разумный результат — ровно 2 года.

То есть авторы проверяют, есть ли 29 число в первом феврале промежутка, и если да, то все годы объявляются високосными, если нет — то все невисокосными. Понятно, что функцию писали из рассчёта на её использование внутри одного года, но в документации об этом ограничении ни слова!

P.S. К слову, поведение аналогичной функции Excel я вообще не понимаю. Первые два примера дают 731/365,333 (откуда берётся 365 1/3 дня?!), последний — уверенное 2.
green_fr: (Default)
Вспомнил недавно, как ещё в институте пытался выучить C. И самая большая проблема была в том, что я не мог найти полный список стандартных функция этого языка. Все языки, которые я учил до тех пор, я учил по книжкам — читаешь вводные главы (как на этом вообще пишутся программы), а потом переходишь к алфавитному указателю функция, чтобы знать, на что тут вообще можно рассчитывать.

А в C почему-то таких списков не было. Были какие-то списки по библиотекам, но не было полного списка библиотек...
Ещё через некоторое время я попытался (более успешно в итоге) выучить java — те же грабли. Ты знаешь какие-то классы, какие-то пакеты, но совершенно нет ощущения полноты знаний, что ты не упустил чего-то, не прошёл мимо нужной и интересной функции.

В этом смысле MatLab действует очень успокаивающе. Полный список Toolboxes доступен на сайте, при этом help каждого пакета начинается со страниц «все функции по категориям» и «все функции по алфавиту» :-)

Profile

green_fr: (Default)
green_fr

June 2025

S M T W T F S
123 4 567
891011121314
15161718192021
22232425262728
2930     

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 6th, 2025 11:56 pm
Powered by Dreamwidth Studios
OSZAR »