Näytetään tekstit, joissa on tunniste MATLAB. Näytä kaikki tekstit
Näytetään tekstit, joissa on tunniste MATLAB. Näytä kaikki tekstit

maanantai 25. elokuuta 2008

memmapfile-funktion käyttö MATLABissa

MATLABissa on jo muutaman version ajan ollut memmapfile-funktio, joka hyödyntää käyttöjärjestelmien tarjoamaa tiedostojen muistiinkuvauspalvelua. Tiedosto voidaan siis kuvata prosessin muistiin ikään kuin se olisi muistissa, vaikka se tosiasiassa onkin vain massamuistissa. Palvelua hyödyntävän ohjelmoijan ei tarvitse itse ladata osia tiedoston sisällöstä muistiin käsittelyä varten, vaan käyttöjärjestelmä hoitaa tämän tylsän ja virhealttiin tehtävän. Palvelu on oikeastaan todella tärkeä ajatellen nykyistä massamuistin ja keskusmuistin suhdetta: massamuistia voi olla tavallisissa mikrokoneissakin teratavu tai useampia, mutta fyysistä muistia on usein vain gigatavu. tai pari. Lisäksi MATLAB tuo vielä oman rajoitteensa muistinkäyttöön, sillä sille ei riitä, että muistia on yhteensä jokin määrä. MATLAB pystyy nimittäin tallentamaan matriiseja vain yhtenäiselle muistialueelle. Lisäksi ainakin Windowsissa MATLABin käytössä oleva muistialue pirstoutuu käytön aikana, jolloin kahden gigatavunkin muistilla varustetussa koneessa pystyy käsittelemään vain muutamaa sadan megan matriisia yhtä aikaa. MATLAB-ohjelmia on myös helppo kirjoittaa niin, että tarvitaan useita kopioita samasta matriisista.

memmapfilen käyttö on onneksi melko yksinkertaista. Oletetaan, että on olemassa 500 megatavun Level 4 MAT-tiedosto aikasarja.mat, jossa matriisi y sisältää jonkin systeemin syötteen rivillä kaksi, vasteen rivillä kolme ja ajan rivillä yksi. Seuraavalla koodilla 

   s = whos('-file', 'aikasarja.mat');
map=memmapfile('aikasarja.mat',...
'Format', {'double' s(1,1).size 'y'},...
'Repeat', 1,...
'Offset', 22);
syntyy objekti map, jossa itse aikasarjoihin pääsee käsiksi notaatiolla map.Data.y. Tässä on ensin whos-funktiolla otettu tiedoston sisältämän matriisin ominaisuudet talteen rakenteeseen s. Matriisin koko on syötetty suoraan memmapfilen Format-argumenttiin, joka tarvitsee lisäksi ohjeen datan tulkitsemiseksi (double) ja nimeämiseksi (y). Tämän jälkeen voi vaikkapa laskea varsin siedettävällä muistinkäytöllä taajuusvaste-estimaatin:
[FRF, frequency] = tfestimate(map.Data.y(2,:), map.Data.y(3,:));
Oleellista on tietää, missä muodossa data on tiedostossa. memmapfile on sen verran matalalla tasolla, että helposti joutuu lukemaan MAT-tiedostoformaatin dokumentaatiota pystyäkseen antamaan oikean arvon Offset-argumentille. Tässä tapauksessa oikea offset on 22, koska matriisin nimen pituus on kaksi tavua (y-kirjain ja null-merkki). Tiedostojen tarkastelussa tarvitaan hyvä tiedostonmuokkain. Paras löytämäni on KHexEdit, joka tosin toimii vain Linuxissa. Ehkäpä samat toiminnot tarjoava ohjelma on olemassa myös Windowsille.

Rekursiivinen hakemistolistaus MATLABissa

Kotikutoinen rekursiivinen hakemistolistaus MATLABissa. Esimerkki käytöstä:
>> pwd

ans =

D:\Ohjelmistot\MATLAB\R2008a\bin

>> s = rlsdir('.');
>> s.name

ans =

.\registry


ans =

.\util


ans =

.\win32


ans =

.\util\mex


ans =

.\win32\accessible


ans =

.\win32\codecs


ans =

.\win32\imageformats


ans =

.\win32\ipp20


ans =

.\win32\mbuildopts


ans =

.\win32\mexopts

>> s = rlsdir('registry');
>> s.name
>> s = rlsdir('util');
>> s.name

ans =

util\mex

>>

Toiminta perustuu oletukseen, että hakemistot . ja .. ovat ensimmäisenä listassa. Tämä ei toteudu ainakaan silloin, jos hakemisto(i)ssa on tiedostoja, jotka alkavat #:lla. Esimerkiksi Emacs jättää jälkeensä tällaisia tiedostoja.

Koodi (jota saa käyttää vapaasti):

function dirs = rlsdir(root)

% DIRS = RLSDIR(ROOT)
% Returns a recursive listing of subdirectories of ROOT in structure DIRS
% similar to that returned by the built-in function DIR. The pathname of
% the NAME field of the structure DIRS is given relative to ROOT.

temp = dir(root); % List the root dir
temp(1:2)=[]; % Remove this directory (.) and upper level (..)
n = 1;
for n = 1:length(temp) % Loop through directories and files
if temp(n).isdir == 1 % If a directory is found ...
temp(n).name = [root '\' temp(n).name]; % concatenate the root level
temp = [temp; rlsdir(temp(n).name)]; % directory name and the newly
end % found directory to a
end % temporary variable and list
m = []; % the contents of the new dir.
for n = 1:length(temp) % Remove all non-directories from the temporary
if temp(n).isdir == 0 % variable.
m = [m ; n];
end
end
temp(m) = [];
dirs = temp; % Return the temporary variable.

end