Jiing’s Blog

Just another WordPress.com weblog

上網學日文–帶了就走

作者:吳權威
出版日期:2002年6月
出版社:碁峰出版

這本書是昨天無聊去圖書館亂逛時看到的,借的時候就被告知過是沒有光碟的,不過我本來就想說拿來翻翻,看看有什麼是我不知道的。看了一下,發現這位作者其實在書最後的整理表中,有好幾個地方是同一個連結出現了二次,上網去查了一下,這位作者出版過的書還真是多。而且包羅萬象。本書另有上網學日文-練功篇,還有一本上網學英文--帶了就走。我想之前priv所提供的早安日語網站,加上這本書裡面有蠻多還不錯的連結,應該有足夠的資料可以學習和閱讀。不過本書的年代久遠,也不知道連結有無失效,暫整理如下: 繼續閱讀

19 三月, 2007 Posted by | Uncategorized, 日語勉強 | 發表留言

上班隨手畫:小龍女的神韻

最近在看神鵰俠侶,覺得小龍女真是美麗(我對這次女主角人選的偏愛也是原因),於是就想要畫出小龍女的神韻,不過由於技巧拙劣,只能畫出飄逸的感覺。原本的相機送修了,這是用手機拍的,不是很清楚。

看來有空要來學painter了(好像是好幾年前就想了:D),好想畫出完稿度較高且上好顏色的圖。

DSC_00017

DSC_00016

另外左下角這個就真的隨便畫了,沒有特別想畫什麼。
DSC_00015

—–

24 三月, 2006 Posted by | Uncategorized | 發表留言

撰寫快速的 MATLAB 程式碼

作者:Pascal Getreuer
譯者:Jiing Deng jiing@jiing.org
原始的pdf檔

九月六日,2005

MATLAB程式語言是剖析式(parsed)的,原始碼是即時直譯的。像C++和Fortran的程式語言比較快,因為它們在變成電腦原生(native)語言前先被編譯。即時剖析的優點是較與平台不相關、具強固性(robustness)和更容易除錯。缺點是在速度上會變慢,負荷會變多,及受限的低階控制。

要彌補速度上的損失,MATLAB提供了能幫助加速的程式碼。此文章討論這些和其它的策略來改善MATLAB原始碼的速度。

* 陣列預先配置
* 向量化的計算和邏輯
* 向量化的參考(Vectorized referencing)

警告!

*先學習程式語言:最佳化(不僅是MATLAB)需要熟悉程式語言的語法和函式。本文並不是MATLAB的教學
*使用註解:最佳化的程式碼是精練和神祕的。為了幫助他人和你自己,記得要加註解。
*不要在它需要被最佳化程式碼之前最佳化它:在最佳化程式碼之前,考慮它是否值得這些心力。如果程式碼很快就會被修改或擴充,無論如何它會被重寫。
*只要最佳化必要的部份:確定程式確實是速度的瓶頸。如果它不是,最佳化只會把程式碼變得難以理解。

1. 速度剖析器(The Profiler)

MATLAB 5.0和較新的版本都包含了一個叫作profiler的工具,它幫助你決定程式裡哪裡是瓶頸。考慮下面的程式:

function result = example1(Count)
for k = 1:Count
result(k) = sin(k/50);

if result(k)

要分析程式的效率,首先啟動profiler,並清除任何舊的profiler資料:
>> profile on
>> profile clear

現在執行程式吧。將輸入的引數變得大些或小些,讓它跑個幾秒。

>> example1(5000);

然後輸入

>> profreport(’example1’)

profiler會在函式上產生一個HTML報表,然後開啟一個瀏覽器視窗。根據系統,profiler的結果可能會與此例有些不同。

MATLAB profile report-Summary

在藍色的「example1」連結上按一下會提供更多的細節:
圖片 1

顯示了最花時間的行數,伴隨著時間、時間的百分比和行數。代價最高的行數是第4和第7行。

2. 預先配置陣列

MATLAB的矩陣變數有動態的引數行和列的能力。例如:

>> a = 2
a =
2
>> a(2,6) = 1
a =
2 0 0 0 0 0
0 0 0 0 0 1

MATLAB會自動地改變矩陣的尺寸大小。在內部,矩陣資料記憶體必須被預先配置予較大的尺寸。如果矩陣可重覆地改變大小–像是在for迴圈裡–此負荷會變得很顯著。要避免經常性的重新配置,用zero命令來「預先配置」矩陣。思考下列的程式碼:

a(1) = 1;
b(1) = 0;

for k = 2:8000
a(k) = 0.99803 * a(k – 1) – 0.06279 * b(k – 1);
b(k) = 0.06279 * a(k – 1) + 0.99803 * b(k – 1);
end

profiler計算此程式碼的時間花費了0.47秒。在執行for迴圈之後,二個陣列都是長度8000的列向量,因此要預先配置,建立8000個元素的空的a和b列向量。

a = zeros(1,8000); % 預先配置
b = zeros(1,8000);
a(1) = 1;
b(1) = 0;
for k = 2:8000
a(k) = 0.99803 * a(k – 1) – 0.06279 * b(k – 1);
b(k) = 0.06279 * a(k – 1) + 0.99803 * b(k – 1);
end

經此修改,程式碼只花費0.14秒(快超過三倍)。預先配置通常很容易,在本例中它只需要決定正確的預先配置大小及新增二行。如果最終的陣列尺寸大小會變動那麼會怎麼樣?一個可能的方法,是在迴圈執行完之後使用陣列尺寸大小的上界(upper bound),並且裁剪掉超出的部份:

a = zeros(1,10000); % 預先配置
count = 0;
for k = 1:10000
v = exp(rand(1)*rand(1));
if v > 0.5 % conditionally add to array
count = count + 1;
a(count) = v;
end
end
a = a(1:count); % 裁剪結果

此程式的平均的執行時間是0.42秒(沒有預先配置),及0.18秒(有預先配置)。

巢狀陣列(cell array)也能被預先配置,使用cell命令來建立想要的尺寸大小。對常常變化大小的巢狀陣列預先配置記憶體,甚至比對雙精度陣列更有效益。

3. 向量化(Vectorization)

要「向量化」一個計算代表說要用向量運算取代平行運算。此策略通常增進十倍的速度。好的向量化是一種必須被發展的技巧,它需要熟悉MATLAB程式語言和有創造力。

3.1 向量化的運算

許多標準的MATLAB函式是「向量化的」,它們能在陣列上操作,就如同函式已經各別地被套用於每一個元素之上。

>> sqrt([1,4;9,16])
ans =
1 2
3 4
>> abs([0,1,2,-5,-6,-7])
ans =
0 1 2 5 6 7

考慮下列的函式:

function d = minDistance(x,y,z)
% 找出介於一個點集合和原點間旳最小距離
nPoints = length(x);
d = zeros(nPoints,1); % 預先配置

for k = 1:nPoints % 計算每一點的距離
d(k) = sqrt(x(k)^2 + y(k)^2 + z(k)^2);
end

d = min(d); % 取得最小距離

對於每一個點,介於它和原點間的距離被計算且儲存在d。然後最小距離可用min來找到。

要向量化距離的運算,用向量運算代換for迴圈:

function d = minDistance(x,y,z)
% 找到介於一個點集合和原點之間的最小距離
d = sqrt(x.^2 + y.^2 + z.^2); % 計算每一點的距離
d = min(d); % 取得最小的距離

修正後的程式碼以向量運算來執行距離運算。x, y和z陣列首先使用逐元素的power運算(.^,用來做乘法和除法的逐元素運算子是.*和./)來計算平方。平方的部份用向量加法相加。最後向量總和的平方根被逐元素計算,產生了一個距離陣列。

minDistance程式的第一版50000個點花了0.73秒。向量化的版本花費的時間少於0.04秒,快了超過18倍。一些對於向量化計算有用的函式:min, max, repmat, meshgrid, sum, cumsum, diff, prod, cumprod, filter。

3.2 向量化的邏輯(Vectorized Logic)

前一節告訴你如何去向量化純粹的計算。瓶頸程式碼通常包含條件式邏輯。就像計算,MATLAB的邏輯運算子被向量化了:

>> [1,5,3]

二個陣列被逐元素比較。邏輯運算以二元的元素傳回「logical」陣列。

這如何使用?對於在邏輯陣列運算上,MATLAB有一些強力的函式:

* find:找出非零元素的索引值(index)。
* any:如果向量中有任何一個元素為非零(或是一個矩陣中的每一行),則為True。
* all:如果向量中所有的元素為非零(或是一個矩陣中的每一行),則為True。

>> find([1,5,3] > find(eye(3) == 1)
ans =
1
5
9

find函式傳回「向量邏輯運算傳回True」的索引(index)。在第一個命令中,1 範例1:移除元素
當在某些逐元素的情況下,陣列元素必須被移除時,此情況通常會產生。例如,這段程式碼從陣列x中,移除所有的NaN和inf元素:

i = find(isnan(x) | isinf(x)); % 找出x中的壞元素
x(i) = [ ]; % 刪除它們

另一個方式是,

i = find(~isnan(x) & ~isinf(x)); % 找出不是Nan也不是inf的元素
x = x(i); % 保留那些元素

範例2:片段的(peicewise)函式

在許多應用程式中,需要以片段的(piecewise)定義來計算函式(例如,spline interpolants)。sinc函式特別有趣,因為在0處有可移除的singularity。

數學式1

對於x ~= 0,sinc能以y = sin(x)./x來計算。此程式使用find和向量化計算來各別處理二個案例:

function y = sinc(x)
% 對於一堆x值,逐元素計算sinc函式。
y = ones(size(x)); % 將y全設為0,因為sinc(0) = 1
i = find(x ~= 0); % 找出所有非零的x值
y(i) = sin(x(i)) ./ x(i); % 計算sinc,其中 x ~= 0

範例3:以meshgrid來繪製圖像

meshgrid函式要二個輸入向量並且藉由複製第一個向量於各列上,和第二個向量於各行上,來將它們轉換它們為矩陣。

>> [x,y] = meshgrid(1:5,1:3)
x =
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
y =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3

上面的矩陣運作的方式像是一個寬度為5,高度為3影像的地圖。
對於已知的像素,位置x可以由x讀取,而位置y可由y讀取。這似乎像是一個記憶體的免費(gratuitous)用法,x和y簡單地紀錄了行和列的位置,不過這很有用。例如,要畫出橢圓(ellipse)。

% 對一個寬150,高100的影像來建立x和y
[x,y] = meshgrid(1:150,1:100);

% 原點為 (60,50) ,尺寸為15 x 40的橢圓
Img = sqrt(((x-60).^2 / 15^2) + ((y-50).^2 / 40^2)) > 1;
% 畫出影像
imagesc(Img); colormap(copper);
axis equal; axis off;

ellipse

畫線幾乎是一樣,只要在方程式中改變即可

[x,y] = meshgrid(1:150,1:100);

% 線 y = x*0.8 + 20
Img = (abs((x*0.8 + 20) – y) > 1);

imagesc(Img); colormap(copper);
axis equal; axis off;

line

Polar函式可以被藉由先將x和y變數以cart2pol函式來轉換,然後被繪出。

[x,y] = meshgrid(1:150,1:100);
[th,r] = cart2pol(x – 75,y – 50); % 轉成極座標
% 對中心(75,50)旋轉
Img = sin(r/3 + th);
imagesc(Img); colormap(hot);
axis equal; axis off;

strangeCircle

範例4:多項式內插

有時候不僅僅會需要執行運算於二個向量的每一對元素間,也要對每個元素的組合。此範例會在polynomial fitting 演算法中告訴你如何做這件事。己知n個點x1, x2, x3, …xn和n 個對應函式值y1, y2, y3, …yn,n-1維度內插多項式係數c0, c1, c2, …, cn-1可以藉由解矩陣方程式而找到。

function2

MATLAB 早就準備好去解決這樣的矩陣方程式,不過困難的部份要被設定。

function c = polyint(x,y)
% 給定一個點集合和函式值x和y,計算內插函式。

x = x(:); % 確定x和y都是行向量
y = y(:);
n = length(x); % n = 點數
%%% 建構矩陣的左手邊 %%%
xMatrix = repmat(x, 1, n); % 建立一個n x n矩陣,每一行都是x
powMatrix = repmat(n-1:-1:0, n, 1); % 建立另一個n x n 指數矩陣
A = xMatrix .^ powMatrix; % 計算指數(power)
c = A\y; % 解決係數的矩陣方程式

建構左手邊矩陣的策略首先是建立二個底數(base)和指數(exponent)的n x n矩陣,然後將它們用逐元素的power運算元.^來放在一起。repmat函式(「複製矩陣」)被用來建立base矩陣xMatrix和指數矩陣powMatrix。

matrix3

xMatrix藉由在行上面重覆行向量x n次來形成。相似地,powMatrix是一個有n-1, n-2, n-3, …, 0重覆遞減列向量n次。MATLAB 4.0和較早的版本沒有repmat函式,請參考6.5節裡的另一個方式。二個矩陣也可以用meshgrid來建立:

[powMatrix, xMatrix] = meshgrid(n-1:-1:0, x);

此函式只有一個範例;對重要的(serious)多項式內插法使用標準的polyfit函式。

左手邊矩陣用像號角(Horner-like)的建構(polyfit.m 45-48行)方式更通用且更具演算法效率。

4 參考運算(Referencing Operations)

MATLAB裡的參考(Referencing)是多變且強到足以讓我們保留一節來討論的。透徹地瞭解參考(Referencing)讓你對編程中各種情況能加以向量化。

4.1 下標 vs. 索引

下標是用來參考矩陣元素最常見的方法,例如,A(3,9)指到第三列,第九行。索引是另一個參考方法。考慮一個10 x 10矩陣A。在內部,MATLAB線性地儲存矩陣資料為一個一維的、100個元素的資料陣列。

matrix

一個索引指到一個元素在此一維陣列中的位置。例如,A(83)指到在第三列,第九行上的元素。

介於下標和索引間的轉換可以sub2ind和ind2sub函式來達成。然而,因為這些是m-file函式,而非快速的內建運算,它更有效率地直接計算轉換。對一個二維的、尺寸大小為M x N的矩陣A,介於下標(i,j)和索引(index)間的轉換為:

A(i,j) A(i + (j-1)*M)
A(index) A(rem(index-1,M)+1, floor(index/M)+1)

索引也能延伸到N維矩陣,以先增加行、然後是列,然後是第三個維度,等等….的索引。下標則是直觀地擴充了,A(. . . , dim4, dim3, row, col)。

4.2 向量化的下標

用子矩陣(submatrices)而非各別的元素是很有用的。這用索引或下標的向量來達成。如果A是一個二維矩陣,向量下標參考有下列語法:

A(rowv, colv)

其中rowv是一個有M個元素的列向量,而colv是一個有N個元素的行向量。二者可能是任意長度且它們的元素可能是依任何順序排成的。如果是一個矩陣的話,它會被重新塑型(reshaped)成一個向量。在向量下標中使用列向量或行向量是沒有差別的。

在運算的右手邊(rhs),向量下標參考會傳回一個元素尺寸大小為 MxN 的子矩陣。

matrix2

如果向量下標矩陣在左手邊(lhs,left-hand side),rhs的結果必須是MxN或是純量大小的。如果有任何元素在目的地的參考被重覆了,例如,A(1,2)和A(2,2)這種不明確、令人混淆的指派:

A([1,2],[2,2]) = [1,2;3,4]

matrix3

這是在其較大索引的來源陣列中指定的(dominate)值。

>> A = zeros(2); A([1,2],[2,2]) = [1,2;3,4]
A =
0 2
0 4

向量下標參考在較高維度中直觀地延伸擴充了。

4.3 向量索引(Vector Indices)

多重元素也可被以向量索引參考。

A(indexv)

其中indexv是一個索引陣列。在右手邊(rhs),向量索引參考傳回和indexv尺寸大小相同的矩陣,如果indexv是一個3×4矩陣,A(indexv)是3 x 4矩陣:

matrix4

然而向量下標參考到塊狀(block-shaped)子矩陣是有限制的,向量索引可以參考到任意形狀。如果向量索引參考是在左手邊(lhs),右手邊(rhs)一定會傳回一個和indexv同樣大小的矩陣或純量。使用向量下標,混淆不清重覆的指派會使用較後面所指派的值。

>> A = zeros(2); A([3,4,3,4]) = [1,2,3,4]
A =
0 3
0 4

4.4 參考的萬用字元

在一個指到整列或整行的下標中使用萬用字元,:。例如,A(:,1)指到第一行中的每一列–整個第一行。這可以結合向量下標,A([2,4],:)指到第二和第四列。

當萬用字元被用於向量索引時,整個矩陣會被參考到。在右手邊(rhs),這總是會傳回一個行向量。

A(:) = 行向量

這常常有用:例如,如果一個函式輸入必須是一個列向量,使用者的輸入可以被以A(:).’快速地重新塑形成列向量。A(:).’是轉成一個行向量然後轉置成列向量(譯註:A(:)’也行)。

在左手邊(lhs)的A(:)指派了所有A的元素,不過不會改變其尺寸大小。例如,A(:) = 8將所有A矩陣的元素變為8。

4.5 以[ ]刪除子矩陣

在一個矩陣中的元素可以藉由指派空矩陣來刪除之。例如,A([3,5]) = [ ]從A刪除了第三和第五個元素。如果這以索引參考來達成,矩陣會被重新塑形(reshape)成列向量。
如果除了一個以外,所有的下標是萬用字元,也能以下標來刪除。A(2,:) = [ ]刪除了第二列。像A(2,1) = [ ]或甚至是A(2,1:end) = [ ]是不被允許的。

5.雜七雜八的技巧

5.1 轉換任何陣列成一個行向量

強制一個陣列成行向量通常是有用的,例如,當撰寫一個期望行向量作為輸入的函式時。此簡易的技巧會將輸入陣列轉換成一個行向量(如果陣列是一個列向量、矩陣、N維陣列或已經是一個行向量)。

x = x(:); % 將x轉換成一個行向量

藉由在此運算後加上轉置運算元「.’」,便可以將陣列轉成列向量了。

5.2 取得陣列中的元素個數

size函式傳回一個內含陣列尺寸大小的向量。用prod,陣列中元素的個數可以被簡要地計算,用

nElements = prod(size(x)) %計算x裡的元素個素

用ndims(x)來取得陣列中維度的數目。
注意:在MATLAB 6.1時,MATLAB引入了一個numel函式來計算元素的個數,不過此函式不回溯相容。

5.3 不使用if敍述來限制(bound)一個值

如果問題是「x值必須至少是a,至多為b」,直觀的方法是用if和elseif敍述式來寫這段程式碼。不幸地是,MATLAB的if敍述很慢。使用min和max函式來將x限制在lowerBound和upperBound範圍之內的方法是:

x = max(x,lowerBound); % 令 x >= lowerBound
x = min(x,upperBound); % 令 x
如果x是一個任意大小的矩陣,這一樣也會作用於每個元素之上。

5.4 找出矩陣或N維陣列的的min/max

給定一個矩陣輸入(沒有其它的輸入),min和max函式沿著行作運算,它會找出每行內的極值。通常找出整個矩陣元素的極值會更有用。重覆min或max函式於行極值上是合理的;
min(min(A))用來找出一個二維矩陣A的最小值。此方法只對min/max呼叫一次(使用轉換到行向量的技巧)且決定了極值元素的位置:

[MinValue, MinIndex] = min(A(:)); % 找到A中最小的元素
% 極小值為MinValue, 它的索引為 MinIndex
MinSub = ind2sub(size(A), MinIndex); % 將MinIndex轉換為下標

最小的元素是A(MinIndex) 或以下標參考的方式是 A(MinSub(1), MinSub(2), …) 。(類似地, 用max來取代min以求得極大值。)

5.5 不以repmat來「重覆向量/將向量如瓦片般鋪設」(Repeating/tiling vectors without repmat)

在MATLAB 5.3版時,repmat函式以m-file而非內建函式來實作。雖然它非常快,它仍有因使用m-file而帶來的間接成本。
因此最標準的MATLAB m-file函式內嵌地執行repmat,而非呼叫它(例如,請見meshgrid.m 41,42,55行),這並不令人驚訝。然而repmat有為了運算於矩陣上的泛用性,而通常我們只需要排列一個向量或純量而已。要重覆一個行向量y於行上n次,

A = y(:,ones(1,n)); % 相當於 A = repmat(y,1,n);

要在列上重覆一個列向量x m次,

A = x(ones(1,m),:); % 相當於 A = repmat(x,m,1);

要重覆一個純量s到一個m x n的矩陣內

A = s(ones(m,n)); % 相當於 A = repmat(s,m,n);

此方法避免了呼叫m-file函式的負擔。它決不會比repmat慢。鑒定家應該注意到repmat.m本身在第52-53行上使用了這個方法。

注意:對於單一鋪排(tiling)運算,所提出的方法並沒有任何超過repmat的速度優勢。然而,當執行許多鋪排(tiling)運算時(像是在for迴圈中取代repmat),它的速度優勢則是引入注目的。

5.6 GUI物件上集合的向量化用法

對於像文字標籤(text label)、按鈕和slider的東西,複雜的圖形使用者介面(GUI)會有上打的物件。這些物件必須全被uicontrol函式以很長的屬性名稱(property name)初始化。例如,要定義三個具有白色背景且文字向左對齊的編輯方塊(edit boxes)(預設是灰色的,且置中對齊):

uicontrol(’Units’, ’normalized’, ’Position’, [0.1,0.9,0.7,0.05], …
’HorizontalAlignment’, ’left’, ’Style’, ’edit’, ’BackgroundColor’, [1,1,1]);
uicontrol(’Units’, ’normalized’, ’Position’, [0.1,0.8,0.7,0.05], …
’HorizontalAlignment’, ’left’, ’Style’, ’edit’, ’BackgroundColor’, [1,1,1]);
uicontrol(’Units’, ’normalized’, ’Position’, [0.1,0.7,0.7,0.05], …
’HorizontalAlignment’, ’left’, ’Style’, ’edit’, ’BackgroundColor’, [1,1,1]);

對三個編輯方塊而言,就有好幾行了。用向量化的呼叫來設定可以減少廢話(字):

h(1) = uicontrol(’Units’, ’normalized’, ’Position’, [0.1,0.9,0.7,0.05]);
h(2) = uicontrol(’Units’, ’normalized’, ’Position’, [0.1,0.8,0.7,0.05]);
h(3) = uicontrol(’Units’, ’normalized’, ’Position’, [0.1,0.7,0.7,0.05]);
set(h, ’HorizontalAlignment’, ’left’, ’Style’, ’edit’, ’BackgroundColor’, [1,1,1]);

此方法也有益於對多個物件在一個地方一次就改變其共享參數。

6. 持續深入

有的時候,寫程式已經寫到不能再被最佳化了,要記在心裡一件事:MATLAB試著成為一個原型語言(prototyping language)。在某些情況下,適當的解法是使用MEX-file(Matlab EXternal interface file,MATLAB外部介面檔)。用一個C或Fortran編譯器,它能產生快速與MATLAB溝通的介面函式。對於相當的m-file程式,MEX-file可輕鬆增進超過十倍(ten-fold)的速度。詳見Mathworks MEX-files使用手冊:

http://www.mathworks.com/support/tech-notes/1600/1605.html

警告:撰寫MEX-files需要很瞭解MATLAB且要熟悉C或Fortran,且開發它會比編寫M-file程式花費更多的時間。然而,它有機會能增進速度。

最後,祝好運及快樂地編程:D

19 十月, 2005 Posted by | Uncategorized | 發表留言

MATLAB 7中的新特性:對於大型資料集的處理

原文出處:http://www.mathworks.com/company/newsletters/digest/nov04/newfeatures.html

MATLAB文摘–2004年11月

MATLAB 7中的新特性:對於大型資料集的處理

作者: Stuart McGarrity
譯者: Jiing Deng

MATLAB 7 引入很多強化機制以支援大型資料集的處理。這些支援包含改善檔案存取、資料儲存的效率、資料處理速度及支援新的64-bit平台。

本文中的教材和範例使用具有Service Pack 1的MathWorks MATLAB Release 14的特性。

大型資料集處理事宜

解決需要處理和分析大量資料的科技運算問題會在你的電腦系統上造成高度的(資源)需求。大型資料集在處理期間花費大量記憶體,並且需要許多運算來計算解。它也會花費很長的時間來從大型資料檔存取資訊。

然而,電腦系統有記憶體限制和有限的CPU速度。可用的資源依處理器和作業系統而變化,作業系統也消耗資源。例如:

*32位元處理器和作業系統可以定義上達2^32 = 4,294,967,296 = 4 GB的記憶體(也就是虛擬定址空間)。

*Windows XP和Windows 2000只配置2GB的虛擬記憶體到每個程序(例如MATLAB)。在UNIX上,配置到程序的虛擬記憶體是由系統組態設定的,一般在3GB左右。

*應用程式(如MATLAB)執行計算,除了使用者工作(user task)以外,會需要儲存空間。

當處理大量資料時,主要的問題是程式的記憶體需求會超過平台上可用的記憶體。例如,在Windows XP上當資料的記憶體需求超過約1.7GB時,MATLAB會產生「out of memory」錯誤。

下列各節描述數種在MATLAB 7中的強化來幫助大型資料集的處理,包含增加的可用記憶體改善了的檔案存取更有效率的資料存儲增加了的處理效能

最大化可用的記憶體

新的64位元平台

64位元版本的MATLAB現在在基於AMD64和Intel EM64T處理器上的Linux平台是可用的。64-bit處理器提供非常大量的可用記憶體,上達2^64 bytes = 18,446,744,073,709,552, 000 bytes (16 exabytes),讓你儲存非常大量的資訊。例如,Google搜尋引擎現在使用2 petabytes的磁碟空間。有16 exabytes,你可以把9,000個Googles放進記憶體裡。

64位元架構的平台解決了處理今日的大型資料集合的記憶體限制,不過並非指其它的事項,例如執行速度和檔案I/O速度。

注意:在64位元平台的MATLAB中,單一矩陣的尺寸大小現在的限制是至多2^32個元素,就像一個65,000x 65,000的方陣(square matrix),會消耗 16 GB。

對Windows XP的記憶體強化

MATLAB 7 增加了在Windows XP下的最大連續記憶體區塊到近乎1.5 GB,相當於18億的雙精度值。

當然,在Windows XP上,MATLAB現在支援3GB切換(3GB switch)啟動選項(boot option),配置額外的1 GB的可定址記憶體到每個程序上。這增加了你可以儲存到MATLAB workspace中資料的總量約到2.7 GB。這相當於33億的隻精度值。此新增的記憶體區塊和MATLAB使用剩下的(記憶體)並不是連續的,所以你不能建立一個陣列來填滿此空間。

觀看可用的記憶體

要看在Windows系統上在MATLAB 7中的可用記憶體是什麼,使用下列的命令。

feature(‘memstats’)

下例顯示具3-GB切換設定的1.2-GB RAM Windows XP系統的結果。你可以看到二個超過1G的大型記憶體區塊,每一個都有總數2.7 GB的記憶體可用。

Physical Memory (RAM):
In Use: 340 MB (1549f000)
Free: 938 MB (3aa4d000)
Total: 1278 MB (4feec000)
Page File (Swap space):
In Use: 236 MB (0ec78000)
Free: 986 MB (3dad9000)
Total: 1223 MB (4c751000)
Virtual Memory (Address Space):
In Use: 296 MB (1283d000)
Free: 2775 MB (ad7a3000)
Total: 3071 MB (bffe0000)
Largest Contiguous Free Blocks:
1. [at 10007000] 1546 MB (60a69000)
2. [at 7ffe1000] 1023 MB (3ffbf000)
3. [at 7c41b000] 28 MB (01c75000)
4. [at 74764000] 28 MB (01c2c000)
5….
======= ==========
2734 MB (aae1a000)

你必須在電腦上安裝足夠的實體記憶體(RAM)以便滿足你的資料存儲的需求。這麼做最小化了將資料分頁到磁碟上(paging the data to disk)的動作,將資料分頁到磁碟上會降低執行效率。

若需更多在MATLAB中最大化可用記憶體的資訊,可參考記憶體管理手冊(Memory Management Guide)

資料存取

文字檔讀取

新的textscan函式讓你存取有任意格式的、非常大的文字檔。此函式相似於textread不過新增了指定檔案辨識子(identifier)的能力,這使得檔案指標可以被追蹤和在整個檔案中來回走動(traverse)。因此檔案可以一次讀一個區塊,在每種時機上改變其格式。

例如,假設我們有一個純文字檔,test12_80211b.txt,其內包含多個不同大小的資料區塊,每個有下列的格式:

二行敍述的標題
一個參數m
一個 p x m 的資料表
test12_80211b.txt 看起來像:

* Mobile1
* SNR Vs test No
Num tests=19
,-5.00E+00,-4.00E+00,-3.00E+00,-2.00E+00,…
1.00E+00,6.19E-07,8.63E-07,6.43E-07,1.84E-07,…
2.00E+00,2.88E-07,4.71E-07,6.92E-07,1.43E-07,…
3.00E+00,2.52E-07,8.11E-07,4.74E-07,8.48E-07,…
4.00E+00,…

* Mobile2
* SNR Vs test No
Num tests=20
,-5.00E+00,-4.00E+00,-3.00E+00,-2.00E+00,-1.00E+00,0.00E+00,…
1.00E+00,6.19E-07,8.63E-07,6.43E-07,1.84E-07,6.86E-07,3.73E-,…
2.00E+00,…

你可以用下列的MATLAB命令來將它讀取進來:
fid = fopen(‘test12_80211b.txt’, ‘r’); % 開啟純文字檔
InputText = textscan(fid, ‘%s’, 2, ‘delimiter’, ‘\n’); % 讀取標題列
HeaderLines = InputText{1}

HeaderLines =
‘* Mobile1’
‘* SNR Vs test No’

InputText = textscan(fid, ‘Num tests=%f’); % 讀取參數值
NumCols=InputText{1}

NumCols =
19

InputText=textscan(fid, ‘%f’, ‘delimiter’, ‘,’); % 讀取資料區塊
Data=reshape(InputText{1},[],NumCols)’;
format short g
Section=Data(1:5,1:5)

Section =
NaN -5 -4 -3 -2
1 6.19e-007 8.63e-007 6.43e-007 1.84e-007
2 2.88e-007 4.71e-007 6.92e-007 1.43e-007
3 2.52e-007 8.11e-007 4.74e-007 8.48e-007
4 1.97e-007 1.64e-007 1.38e-007 6.17e-007

For improved data access speed, in this release of MATLAB the reading of comma-separated-value (CSV) files is an order of magnitude faster.
對於改善的資料存取速度方面,在本MATLAB釋出版本,讀取逗號分隔值(comma-separated-value ,CSV)檔是快了有一個規模(magnitude)。譯註:應是10倍。

MAT檔案壓縮
在MATLAB 7中的save命令現在在寫入MAT檔到磁碟前便壓縮了資料。這導致對於可壓縮的(非隨機的)資料集會有較小的檔,對於在網路上(over network)非常大的資料檔則有較快的讀取速度。

資料存儲的效率

MATLAB 7現在提共整數和單精度數學(運算)。此新的能力使得處理用其原生的(native)型式來處理整數和單精度資料變得可能,導致記憶體使用更有效率及有能力處理更大的、非雙精度的資料集。

例如,當你以原生(native)的方式儲存時,與轉換(cast)並以雙精度(double)儲存相比,你可以處理最多達八倍的8-bit整數值。所以在Windows XP上(沒有3-GB的切換),你最多能讀入一個大小高達1.5 GB的8-bit整數值的檔,而當你需要將資料以雙精度儲存時,有如前述的180 MB的限制。(這是理論上的極大值且可能沒有可用的空間來儲存任何運算的答案。)詳見2004年七月MATLAB文摘中的文章「MATLAB 7中的整數和單精度數學(運算),Integer and Single-Precision Math in MATLAB 7」以獲得更多的資訊。

資料處理效能

改進了的執行速度

MATLAB 7 對於大型資料集問題的較快執行,引入了一堆處理速度的強化機制。這些包含了用於大多數MATLAB支援平台的處理器廠商提供的最佳化的基本線性代數子程式(Basic Linear Algebra Subprograms,BLAS)函式庫,包含IntelÆ Math Kernel Library (MKL)AMD Core Math Library (ACML),和經由Macintosh上Accelerate framework的BLAS函式庫。當然也有用於極大化FFT工作執行速度的最新版本的FFTW(3.0)常式(routine)。

JIT加速器現在涵括了所有數值的資料類型,例如複數變數和函式呼叫(當被函式呼叫時),增加更多MATLAB程式語言的速度。它也產生了對最佳化的整數運算執行的MMX指令。在8-bit整數的情況中,這導致比雙精度(double)快了八倍的執行速度。

新的大型資料集處理的特色

其它支援處理大型資料集的新特性包括了有:
*在互動的資料分析期間,可在陣列編輯器(Array Editor)裡觀看較大的數值陣列的能力(最多達500,000個元素)。
*巢狀函式,允許inner函式看到母函式的workspace。讓你介於函式間共享大型資料集的特性,例如在GUI裡,不需要使用全域(global)變數,或如函式參數般以值傳遞資料。在下面的例子裡,巢狀函式process可以在母函式percentNonzero的workspace中看到如street1的變數。

function y = percentNonzero(filename, scalevalue, thresholdvalue)
%PERCENTNONZERO Calculate the percentage of non-zero elements
% P = PERCENTNONZERO(‘FILENAME’, SCALEVALUE, THRESHOLDVALUE)
% returns the percentage of non-zero elements in an image read
% from the file FILENAME, scaled by the value SCALEVALUE and
% thresholded at a value of THRESHOLDVALUE.
%
% Example:
% p=percentNonzero(‘street1.jpg’,1.5,140);

street1 = imread(filename); % 從檔案讀進影像
process(scalevalue, thresholdvalue); % 縮放和用門檻值來過濾影像

% 找出非零元素的百分比
y = 100 * sum(street1(:))/numel(street1);

function process(scaleval, threshval)
% 縮放影像
street1 = street1 * scaleval;

% 用門檻值來過濾影像以建立邏輯陣列
street1 = street1 > threshval;
end
end

新的M-Lint Code Checker通知你,讓你能夠移除無用變數來最小化你的程式碼的記憶體使用量。若需更多關於M-Lint的資訊,請見在MATLAB News and Notes的2004年十二月的文章「清理你的程式碼!(Clean Up Your Code!)」

總結

MATLAB 7裡有一堆新工具和能力讓你處理更大的資料集合,讓你處理更大和更複雜的工程和科學問題,並且用更少的時間來解決它。

25 九月, 2005 Posted by | Uncategorized | 10 則迴響

Hello wordpress!

剛剛想?用上回和NetNewsWire一齊買的MarsEdit來編輯我在 WordPress.com的這個blog,????功,後來看了zonble寫的這篇,看來好?是?自己架站?能改,晚點?來研究這個站的功能好了

 
?了,感?zonble給我邀請函,我?有wordpress?以玩:D 

24 九月, 2005 Posted by | Uncategorized | 2 則迴響