Tuesday, August 09, 2011

Aventuri cu Matlab mex sub linux x86_64

Am un script Matab care foloseste bucata de cod de pe net care foloseste un third-party mexeig.c, care la randul sau foloseste functia dsyevd() din Lapack. Sub Windows, mai demult nu mai stiu cum, compilasem .c -ul in mex si mergea foarte bine.Din pacate, intreg script-ul dura vreo doua zile pe 3 threaduri ale PC-ului de la birou.

Azi, ca sa nu imi ocup din nou comp-ul pentru 2 zile, mi-am zis sa copii codul pe serverul sub Linux si sa-l rulez acolo pe 6 threaudri (tip: startworkers 6, si apoi matlabpool serverplus).

Cand colo, pac eroare ca nu stie mexeig(). Dupa ca ma gandesc putin, imi dau seama ca nu compilasem mexeig.c sub noua arhitectura. Bine, bag repede un mex mexeig.c. Pac, nu gaseste dsyevd la link-editare, undefined reference. Bine din nou, bag reloaded un mex mexeig.c -llapack. Pac, skipping incompatible library vreo 4 lapack-uri si in continuare undefined reference. Si in plus, la deruta, si un warning ca folosesc gcc 3.4.6 in timp ce minimul testat de ei este 4.0.0.

Eu ma gandesc, bineinteles, ca e problema cu gcc-ul. Injur in gand administratorul care tine o versiune antica si acceptata de CentOS 4.8, cu un gcc antediluvian, si ma gandesc sa-mi instalez o varianta locala de gcc 4.x. Pierd vreo 40 de minute pe net, documentatie, cauta repository CentOS 5.x, trag un rpm cu gcc-4.1.2, ii zic de la obraz un rpm -i --test gcc..., bineintelesc ca nu are dependecies necesare. Mama lui de administrator, imi zic in gand. Dead end, timp pierdut.

Apoi, ca din intamplare, bag un gcc4. De fapt nu din intamplare, vazusem prin lib un folder cu niste librarii gcc 4.1.2. Ce sa vezi, gcc4 merge. E instalat si gcc 4.1.2, dar sub numele de gcc4, nu gcc. Bine, zic, acum cum dracu' il fac sa-l vada si matlab-ul, ca in mex -setup imi apare doar gcc-ul vechi. Iar documentatie, aflu ca exista un mexopts.sh care defineste comenzile si optiunile folosite de Matlab la compilare, intru, replace gcc cu gcc4, dau victorios un mex mexeig.c -llapack, la fel. Skipping incompatible library, undefined reference. Mama naibii. Macar warning--ul se dusese, deci folosea versiune noua de gcc. Toate astea au durat inca vreo juma de ora.

Exasperat, dau un View (F3) din Midnight Commander pe liblapack.so.3.0.3, sa vad, ce dracu' nu gaseste dsyevd, te pomeni ca nu e definita in librarie, sau mai stiu io ce. Si-mi sare in ochi un i386. Nu realizez pe moment, dar dupa vreo 5-10 minute subconstientul ma trage de maneca: i386 ?!? Pe 64 biti?

Mama ei de porcarie, exista un folder lib64 in usr, dar acolo n-are lapack. Asta e, imi zic, CentOS-ul asta are numai versiunea perfect inutila i386, de ce naiba n-are si pe 64 de biti? Iar fugi pe net, cauta un repository, trag un rpm cu liblapack x86_64, dezarhiveaza intr-un folder local, mex -llapack -L/home/... mexeig.c. L-am prins, zic. Cand colo, stupoare. Undefined reference. Nu mai da skipping incompatible library, deci libraria e buna, de ce naiba nu merge?

Ma uit cu F3 in librarie, caut dsyevd, exista, dar vad si multe _ si imi aduc aminte ca e o chestie cu astea. Intru in mexeig.c si inlocuiesc apelul lui dsyevd cu dsyevd_ (imi aduc aminte ca am mai facut asta odata, probabil cand am compilat pe Windows). In sfarsit, merge!

In total, am irosit vreo ora si jumatate, plus un sfert de ora postul asta.

Lectii din treaba asta:
1. Skipping incompatible library se refera la arhitectura pe care a fost compilata libraria (i386, x86_64 etc). nu la versiunea gcc sau mai stiu eu ce.
2. Poti sa adaugi un _ la numele functiei cand nu merge sa link-editezi cu librarii din astea publice si n-ai idee de ce.
3. gcc mai poate avea si numele gcc4

Update. Ehei, dragii mosului, eu inca nu testasem daca mexeig-ul compilat chiar merge. Adica m-am oprit la compilarea si link-area cu succes. Mai departe, cand dau sa rulez, sare cu o eroare run-time cum ca nu gaseste liblapack-ul. Noroc ca vazusem in help-ul lui mex ca, daca compilez cu o librarie dintr-un folder oarecare, tre sa modific si path-urile ca Matlab-ul chiar sa gaseasca libraria respectiva la run-time. Asa ca le-am adaugat frumusel intr-un script fix inainte de a starta matlab-ul (matlab-ul fiind pornit din script, e child process si mosteneste environmentul acestuia):

#!/bin/bash

LD_LIBRARY_PATH=:/home/...$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

cd "CS/Ale mele"
matlab
Au trebuit cea modificari fata de ce zicea help-ul Matlabului, adica am pus ":" inainte de calea mea, si nu intre (pentru ca LD_L... default continea un ":" la inceput), si a trebuit si "$", desigur.

Si inca nu m-a lasat. Cica nu gaseste nici libraria blas. Asa ca ia-o si pe asta de pe net si dezarhiveaz-o in acelasi usr local. Intr-un final, merge.

Update 2  Merge pe dracu! Da, merge daca rulez pe un singur thread. Daca insa incep un matlabpool si rulez codul in parfor, s-a dus. Iarasi nu gaseste liblapack-ul. Problema este ca, in acest caz, codul este executat de catre workers, care nu mostenesc environmentul de la Matlab-ul mare, pentru ca ei sunt creati independent, cu daemon-ul mdce. Asa ca ce-am facut: in primul rand, am adaugat noua LD_LIBRARY_PATH atat in bashrc cat si in bash_profile, si le-am scos din script-ul meu. Sa fie mereu definit mereu si peste tot, ce naiba. Apoi am dat un source, cica, apoi am si repornit vncserver ca sa ma loghez inca o data (nu stiu daca chiar a fost un logout pe bune) ca sa fiu sigur ca s-au citit fisierele din nou. Apoi am reastartat daemon-ul mdce. Asta era chestia esentiala. Acum mdce a re-pornit dintr-un terminal, care mostenise environment-ul bun de la bashrc, deci si mdce il mosteneste, si apoi toti workerii creati de mdce. Se pare ca, intr-un sfarsit, merge (a treia oara)!

Labels: ,

Tuesday, August 02, 2011

Writing tips

În sfârşit m-am apucat de scris lucrarea. Ca de obicei, cheful mi-a venit la scurt timp după ce am început - cheful vine mâncând. Pe la 13 m-am apucat de scris primele rânduri, la 14 scriam în draci. Până spre 17, cand m-a lăsat cheful, dar de altfel scrisesem mare parte din text (descrierea algoritmului lui Elad şi al lui Duarte).

Lecţii de ţinut minte:

1. Cheful vine scriind. Mai ales cand ai ceva pregătit dinainte (de ex. ppt). Lecţia asta o ştiam demult, dar trebuie resubliniată mereu.

2. Sari peste introducere. Scrie partea mai uşoară (descrierea algoritmului, a sistemului etc.) şi lasă polologhia de introducere la sfârşit.

3. Când vine cheful, scrie fără întreruperi. Nu scrie ecuaţii, fără formatare Latex, nu căuta comenzi Latex pe net. Scrie grosul textului, că aici e problema.

Labels: