-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathReport.tex
More file actions
683 lines (585 loc) · 28.9 KB
/
Report.tex
File metadata and controls
683 lines (585 loc) · 28.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\documentclass[10pt,a4paper]{article}
%\twocolumn
%//////////////////////////////////////////////////////////////////////
\textwidth 16cm
\textheight 23cm
\topmargin -1.5cm
\oddsidemargin 0cm
\parindent 0cm
%//////////////////////////////////////////////////////////////////////
%\usepackage[pdftex]{graphicx}
\usepackage{natbib}
\usepackage{bibentry}
\usepackage{amsmath}
\usepackage{color}
\usepackage{url}
\usepackage[final]{mcode}
\definecolor{myyellow}{rgb}{1,1,0.95}
\definecolor{mygreen}{rgb}{0,0.6,0}
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
\definecolor{mymauve}{rgb}{0.58,0,0.82}
\lstset{
backgroundcolor=\color{myyellow}, % choose the background color; you must add \usepackage{color} or \usepackage{xcolor}; should come as last argument
%basicstyle=\footnotesize, % the size of the fonts that are used for the code
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
breaklines=true, % sets automatic line breaking
captionpos=b, % sets the caption-position to bottom
commentstyle=\color{mygreen}, % comment style
deletekeywords={...}, % if you want to delete keywords from the given language
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
extendedchars=true, % lets you use non-ASCII characters; for 8-bits encodings only, does not work with UTF-8
firstnumber=1, % start line enumeration with line 1000
frame=single, % adds a frame around the code
keepspaces=true, % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible)
keywordstyle=\color{blue}, % keyword style
language=Matlab, % the language of the code
morekeywords={*,...}, % if you want to add more keywords to the set
numbers=none, % where to put the line-numbers; possible values are (none, left, right)
numbersep=5pt, % how far the line-numbers are from the code
numberstyle=\tiny\color{mygray}, % the style that is used for the line-numbers
rulecolor=\color{myyellow}, % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here))
showspaces=false, % show spaces everywhere adding particular underscores; it overrides 'showstringspaces'
showstringspaces=false, % underline spaces within strings only
showtabs=false, % show tabs within strings adding particular underscores
stepnumber=2, % the step between two line-numbers. If it's 1, each line will be numbered
stringstyle=\color{mymauve}, % string literal style
tabsize=2, % sets default tabsize to 2 spaces
title=\lstname % show the filename of files included with \lstinputlisting; also try caption instead of title
}
\newcounter{example}[section]
\newenvironment{example}[1][]{\refstepcounter{example}\par\medskip
\noindent \textbf{Example~\theexample. #1} \rmfamily}{\medskip}
%\pagestyle{empty}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\begin{document}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\title{Guidelines for writing efficient MATLAB$^{\text{\small{\textregistered}}}$ codes}
\author{Reza~Sameni\footnote{Department of Biomedical Informatics, Emory University School of Medicine, GA 30322, US, Web: \texttt{www.sameni.info}, Email: \texttt{rsameni@dbmi.emory.edu}}\\
%{\footnotesize reza.sameni@gmail.com}\\
%{\footnotesize Sharif University of Technology, Tehran, Iran}\\
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
Revision: 6 Aug, 2020}
%{\footnotesize Laboratoire des Images et des Signaux, Grenoble, France}\\
%{\footnotesize Sharif University of Technology, Tehran, Iran}\\
%{\footnotesize Email: reza.sameni@lis.inpg.fr}
\date{}
\maketitle
\thispagestyle{empty}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\begin{abstract}
In this tutorial some of the general methods of writing more efficient MATLAB codes are reviewed. It is assumed the reader is already familiar with the syntax and environment of MATLAB.
\end{abstract}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\section{Introduction}
\label{sec:introduction}
MATLAB\footnote{MATLAB stands for `Matrix Laboratory'.} is one of the most practical software used for numerical calculations, signal processing and machine learning. It is a programming environment and language, which has been optimized for matrix computations. The computational core of MATLAB is the LAPACK and BLAS libraries which were originally written for matrix calculations in FORTRAN. The first versions of MATLAB were just an interface to these libraries. However, it soon evolved into a programming language with many functions and toolboxes for various applications.
In this short tutorial we review some of the general guidelines for writing more efficient MATLAB codes. By efficient we mean more compact code size, better memory access, and shorter execution time. Note that some of these properties are machine dependent concepts. The later presented performance benchmarks have been achieved on a 2.3~GHz Quad-Core Intel Core i7 Macbook Pro, with 32~GB of RAM, and 8~MB of L3 Cache memory.
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\section{General guidelines}
\label{sec:general}
General guidelines for improving MATLAB codes:
\begin{enumerate}
%{\setlength{\rightmargin}{.5cm}\setlength{\leftmargin}{.5cm}\setlength{\listparindent}{.5cm}}
\item Improve the algorithm before attempting to optimize the code.
\item Benefit from the matrix abilities of MATLAB and its built-in functions.
\item Avoid writing the entire program in a single m-file script. One should break down a program into separate m-file functions. This also will help the reuse of functions and creating (open-source) toolboxes.
\item Comment the codes.
\item MATLAB version 6.5 and later support object-oriented programming. This feature can be used to make more structured and reusable codes.
\end{enumerate}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\section{Some of the general features of MATLAB}
\label{sec:features}
%MATLAB is case-sensitive (`a' and `A' are different variables).
MATLAB is an `interpreter' language, which can also use pre-compiled components. This is a good feature for debugging programs and software development. But at the same time it makes MATLAB rather slow (as compared to languages such as C and C++). It is therefore better to use its very efficient components-- known as built-in functions-- as much as possible, rather than using long scripts with nested for-loops and if-conditions. All the predefined MATLAB constants are in fact built-in functions. For example:
\begin{itemize}
\item \texttt{pi} is $4\times\arctan(1)$
\item \texttt{i} and \texttt{j} are $\sqrt{-1}$. One can always redefine \texttt{i = sqrt(-1)} if it is overloaded by a previous m-file script.
\item \texttt{eps(x)} and \texttt{eps(single(x))} are the positive distance from \texttt{abs(x)} to the next larger in magnitude floating point number of the same precision as \texttt{x}.
\item \texttt{realmin} and \texttt{realmax} are machine dependent single- or double-precision positive floating point numbers.
\item \texttt{inf} returns the IEEE arithmetic representation for positive infinity, which is also produced by operations like division by zero, e.g. 1.0/0.0, or from overflow, e.g. $\exp(1000)$. It may also be used in matrix form: \begin{lstlisting}
>> a = inf(2,2)
a =
Inf Inf
Inf Inf
\end{lstlisting}
\item \texttt{NaN} is the IEEE arithmetic representation for not-a-number. A NaN is obtained as a result of mathematically undefined operations like 0.0/0.0 or inf$-$inf. It may be used in matrix form as follows:
\begin{lstlisting}
>> nan(3)
ans =
NaN NaN NaN
NaN NaN NaN
NaN NaN NaN
\end{lstlisting}
\end{itemize}
All of these parameters are in fact built-in functions. One can check whether a variable or function is a built-in or not as follows:
\begin{lstlisting}
>> type i
i is a built-in function.
\end{lstlisting}
or:
\begin{lstlisting}
>> exist('i')
ans =
5
\end{lstlisting}
Built-ins may be overloaded by constants or functions. For example, \texttt{i=1} or:
\begin{lstlisting}
function F= fft(x)
F = x.^2
\end{lstlisting}
One may clear the over-loaded values to retrieve the original built-in values:
\begin{lstlisting}
>> clear i j
\end{lstlisting}
It is possible to use recursive functions in MATLAB. For example, the following calculates $n!=1\times 2 \times \ldots \times n$:
\begin{lstlisting}
function f = fact(i)
if i < 2
f = 1;
else
f = i*fact(i-1);
end
\end{lstlisting}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\section{Memory access}
\label{sec:memory}
MATLAB can dynamically allocate memory:
\begin{lstlisting}
>> a(1,3) = 5
a =
0 0 5
>> a(2,4) = 6
a =
0 0 5 0
0 0 0 6
\end{lstlisting}
However one can also pre-allocate the required memory:
\begin{lstlisting}
>> a = zeros(1000,200);
\end{lstlisting}
which makes the codes run much faster, especially for large arrays. Let us see an example:
\lstinputlisting[language=Matlab, caption= \lstname]{samplecodes/samplecodes.m}
running this code on our benchmark system resulted in:
\begin{lstlisting}
dt1_mn = 0.1402
dt1_std = 0.0183
dt2_mn = 0.0697
dt2_std = 0.0070
ratio_mn = 2.0509
\end{lstlisting}
which shows that the code with preallocation has been twice as fast on average (the ratio can vary from one system to another). In similar examples -- depending on the CPU, RAM, Cache, required memory, and the type of computation-- a code may run orders of magnitude faster when one pre-allocates the required memories. Pre-allocation may also be used for variable length vectors which have an upper-bound of required memory:
\begin{lstlisting}
% Note: This code is just for memory allocation illustration, but it is
% not efficient in speed. You will see the reason in later sections.
N = 1000;
a = rand(N,1);
b = zeros(size(a));
k = 0;
for i = 1 : N
if(a(i) > 0.5)
k = k + 1;
b(k) = a(i);
end
end
b = b(1 : k);
\end{lstlisting}
The downside of memory pre-allocation is when huge amounts of memory are required, which may not be allocated in a single memory block. Check Matlab documents, the array size limit or preference panel of your MATLAB installation for more information.
%Test the following examples (and change the loop ranges and matrix sizes depending to your system's resources):
%\begin{lstlisting}
% >> % compare the following codes:
% >> A = zeros(50000,100000);
% Error using zeros Requested 50000x100000 (37.3GB) array exceeds maximum array size preference.
% Creation of arrays greater than this limit may take a long time and cause MATLAB to become unresponsive. See array size limit or preference panel for more information.
%
% >> for i = 1 : 100000 % this one works
% B(:,i) = zeros(50000,1);
% end
%\end{lstlisting}
One can use the function \texttt{pack} which performs memory garbage collection by saving the current workspace on the hard disc, clearing the workspace, and reloading the workspace from the hard disc. It is very useful for defragmentation of the memory in long-running programs that continuously allocate and clear variables. Note that it is not efficient to use \texttt{pack} so frequently, since it slows down the code. For example:
\begin{lstlisting}
for i = 1 : N
if (mod(i,100)==0) % perform packing every 100 iterations
pack;
end
f(i); % a user-defined function which fragments the memory
end
\end{lstlisting}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\section{Speed optimization}
\label{sec:speed}
MATLAB is excellent in matrix calculations. So it is very important to use its matrix abilities rather than using for-loops or if-conditions, which operate on single entries of vectors and matrices.
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\subsection{Array indexing}
There are three ways of array indexing in MATLAB:
\begin{enumerate}
\item \textit{Subscripted}
\begin{lstlisting}
>> A = [11 14 17;...
12 15 18;...
13 16 19];
>> A(1,2)
ans =
14
>> A([1 2],2)
ans =
14
15
>> A(1:3,1)'
ans =
11 12 13
>> A(1:end,2)
ans =
14
15
16
\end{lstlisting}
\item \textit{Linear}
\begin{lstlisting}
>> A(1)
ans =
11
>> A(4)
ans =
14
\end{lstlisting}
MATLAB matrices are stored in column order (unlike C where matrices are stored in row order). As a result, for an $M\times N$ matrix \texttt{A}, subscript and linear indexings can be related to each other as follows:
\begin{lstlisting}
A(i + (j-1)*M) % which is equivalent to A(i,j)
\end{lstlisting}
and
\begin{lstlisting}
A(rem(index-1,M)+1,floor((index-1)/M)+1) % which is equivalent to A(index)
\end{lstlisting}
Note that by using the colon operator (\texttt{:}) one can convert a multi-dimensional matrix to a column vector (obtained by stacking its columns under one another):
\begin{lstlisting}
>> A(:)
\end{lstlisting}
This feature can be used to, for example, change the entries of a matrix without reshaping it:
\begin{lstlisting}
>> A(:) = 1;
\end{lstlisting}
\item \textit{Logical}
\texttt{logical} is a data-type in MATLAB, which is returned by many of the comparative operators. This feature is helpful in writing compact and fast codes without using if-conditions. Let us take a look at some examples:
\begin{lstlisting}
>> [4 5 3] > [1 2 6]
ans =
1 1 0
>> whos
Name Size Bytes Class
ans 1x3 3 logical array
Grand total is 3 elements using 3 bytes
>> A = 6 : 10;
>> A(logical([0 0 1 0 1]))
ans =
8 10
>> A(A > 7)
ans =
8 9 10
>> B = randn(3)
B =
-0.0956 -1.3362 -0.6918
-0.8323 0.7143 0.8580
0.2944 1.6236 1.2540
>> C = rand(3)
C =
0.9501 0.4860 0.4565
0.2311 0.8913 0.0185
0.6068 0.7621 0.8214
>> C(B > 0)
ans =
0.6068
0.8913
0.7621
0.0185
0.8214
\end{lstlisting}
\end{enumerate}
The indexing features of MATLAB are useful for replicating a vector or a matrix:
\begin{lstlisting}
>> A = [1 5]
A =
1 5
>> A([1 2 1])
ans =
1 5 1
>> V = [1:5]';
>> V(:,ones(3,1)) % This is known as the "Tony's trick"!
ans =
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
\end{lstlisting}
Suppose we want to make a 5$\times$5 matrix with all entries equal to 10. Try the following two ways:%\footnote{Note that MATLAB is case-sensitive (`a' and `A' are different variables).}:
\begin{lstlisting}
>> A = 10*ones(5); % first method
>> a = 10; A = a(ones(5)); % second method
\end{lstlisting}
Another example:
\begin{lstlisting}
>> a = magic(3)
a =
8 1 6
3 5 7
4 9 2
>> N = 2;
>> a(:, N(ones(1, 3)))
ans =
1 1 1
5 5 5
9 9 9
\end{lstlisting}
We can use a similar approach for eliminating some of the matrix entries. For example in order to remove the NaN and Inf entries of a matrix, try the following three equivalent methods:
\begin{lstlisting}
>> % first method:
>> i = find(isnan(x) | isinf(x));
>> x(i) = [];
>> % second method:
>> x(isnan(x) | isinf(x)) = [];
>> % third method:
>> x = x(~isnan(x) & ~isinf(x));
\end{lstlisting}
Check the helps for the following MATLAB functions: \texttt{meshgrid}, \texttt{repmat}, \texttt{reshape}, \texttt{find}, \texttt{any}, and \texttt{all}, for relqted items.
By combining the array indexing features with logical data-types, many of the matrix manipulations may be done without the need of for-loops and if-conditions.
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\subsection{Vectorized computations}
We now use some of the noted MATLAB features in a few computational examples. We will make use of the following MATLAB functions: \texttt{zeros}, \texttt{ones}, \texttt{toeplitz}, \texttt{pascal}, and \texttt{hankel}.
\begin{example}{Signal generation}
\begin{lstlisting}
>> N = 5000;
>> fs = 500; % Hz
>> f0 = 3.8; % Hz
>> t = [0 : N-1]/fs;
>> x = sin(2*pi*f0*t) .* exp(-t.^2/2);
\end{lstlisting}
\end{example}
\begin{example}{Inner product}
\begin{lstlisting}
>> a = [1 2 3];
>> b = [4 5 6];
>> a*b' % first method
ans =
32
>> sum(a.*b) % second method
ans =
32
\end{lstlisting}
\end{example}
Scalars may be added, subtracted or multiplied by vectors or matrices using their corresponding operators. Vectors and matrices may also be divided by scalars in the same manner; but in order to divide a scalar by a vector or matrix, one should use the \texttt{./} operator instead of the \texttt{/} operator.
When both of the operands are nonscalar (vectors or matrices), \texttt{*}, \texttt{\^}, and \texttt{/} are used for matrix operations and \texttt{.*}, \texttt{.\^}, and \texttt{./} are used for operations on the entries.
\begin{example}{Clipping a signal}
\begin{lstlisting}
>> x = max(x, SOME_LOWER_BOUND); % clip from the bottom
>> x = min(x, SOME_UPPER_BOUND); % clip from the top
\end{lstlisting}
\end{example}
\begin{example}{subtraction of a vector from all the columns of a matrix}
\begin{lstlisting}
>> a = [1 : 5]';
>> b = eye(5);
>> b - a(:,ones(5,1))
ans =
0 -1 -1 -1 -1
-2 -1 -2 -2 -2
-3 -3 -2 -3 -3
-4 -4 -4 -3 -4
-5 -5 -5 -5 -4
\end{lstlisting}
\end{example}
\begin{example}{Multiplying vectors in matrices}
Try the following four methods
\begin{lstlisting}
>> N = 3000;
>> x = randn(N,1);
>> F = randn(N);
>> Y1 = x(:,ones(N,1)).*F; % 1st in speed
>> Y2 = diag(sparse(x)) * F; % 2nd in speed
>> Y3 = sparse(diag(x)) * F; % 3rd in speed
>> Y4 = diag(x) * F; % 4th in speed
\end{lstlisting}
In the above, \texttt{sparse} is a special data-type in MATLAB, which is efficient for manipulating matrices with many zero entries. Check the help for the \texttt{sparse} and \texttt{full} functions.
\end{example}
\begin{example}{Normalization of the columns of a matrix}
\begin{lstlisting}
>> vmag = sqrt(sum(v.^2));
>> v = v./vmag(ones(1,size(v,1)),:);
\end{lstlisting}
\end{example}
\begin{example}{First order difference}
\begin{lstlisting}
>> d = sin(2*pi*[0:999]*15/1000);
>> df = d(1 : end-1) - d(2 : end);
\end{lstlisting}
\end{example}
\begin{example}{Using the built-in filter function for vectorizing recursive calculations}
\begin{lstlisting}
>> L = 1000;
>> A = 1;
>> % bad coding style:
>> for i = 1 : L-1
>> A(i+1) = 2*A(i) + 1;
>> end
>> % good coding style:
>> y(i) = (tmp(N/2) + tmp(N/2+1))/2;
>> A = filter(1,[1 -2],ones(1,L));
\end{lstlisting}
\end{example}
\begin{example}{Zero-order holding of uniformly sampled data}
\begin{lstlisting}
>> N = 4;
>> x = [1 5 3];
>> x = upsample(x,N); % x = [1 0 0 0 5 0 0 0 3 0 0 0];
>> x = filter(ones(N,1),1,x);
x =
1 1 1 1 5 5 5 5 3 3 3 3
\end{lstlisting}
\end{example}
\begin{example}{Zero-order holding of non-uniformly sampled data}
\begin{lstlisting}
>> a = 1; b = 5; c = 3;
>> x = [a 0 0 0 b 0 0 c 0 0 0 0]; % => y = [a a a a b b b c c c c c];
>> validin = find(x);
>> x(validin(2 : end)) = diff(x(validin));
>> x = cumsum(x)
x =
1 1 1 1 5 5 5 3 3 3 3 3
\end{lstlisting}
\end{example}
\begin{example}{Median filter of order N}
\begin{lstlisting}
>> x = randn(1000,1);
>> N = 20;
>> y = x;
>> if(mod(N,2)==1) % Odd length median filter
>> for i = (N+1)/2 : length(x)-(N-1)/2
>> tmp = sort(x(i-(N-1)/2 : i+(N-1)/2));
>> y(i) = tmp((N+1)/2);
>> end
>> else % Even length median filter
>> for i = N/2 : length(x)-N/2
>> tmp = sort(x(i-N/2+1 : i+N/2));
>> end
>> end
\end{lstlisting}
\end{example}
\begin{example}{Moving average filter of order N}
\begin{lstlisting}
>> % first method
>> x = randn(1000,1);
>> N = 20;
>> y = filter(ones(N,1)/N,1,x);
>> % second method
>> y = cumsum(x)/N;
>> y(N+1 : end) = y(N+1 : end) - y(1 : end-N);
\end{lstlisting}
The second method in this example has used the following property of moving average filters:
\begin{equation}
\label{eq:CIC1}
H(z) = 1+z^{-1}+z^{-2}+\ldots+z^{-N+1}=\frac{1-z^{-N}}{1-z^{-1}}
\end{equation}
The last fraction in this equation is known as the \textit{cascaded integrator comb (CIC)} filter, which is a very practical filter for DSP and FPGA implementation of down-converters and up-converters in telecommunications systems. Its efficiency is due to the fact that it only needs summations and subtractions for its implementation, which are more economic than multipliers, and a memory for keeping the last $N$ input samples.
Although the frequency response of (\ref{eq:CIC1}) is a $\text{Sinc}(\cdot)$ function with N lobes and an attenuation of about 13~dB in its first side-lobe (which is rather poor for a lowpass filter), by cascading several stages of such filters, better performance is achieved:
\begin{equation}
\label{eq:CIC2}
H(z) = \Big(\frac{1-z^{-N}}{1-z^{-1}}\Big)^R
\end{equation}
Such filters are usually followed by a down-sample of order $N$. A similar filter is also used for up-conversion of signals in transmitters.
\end{example}
\begin{example}{Calculation of two-dimensional functions}
Consider the two-dimensional function $F(x,y)=xe^{-x^2-y^2}$. It can be calculated efficiently as follows:
\begin{lstlisting}
>> x = (-2 : 2); % arbitrary initial values
>> y = (-1.5 : .5 : 1.5); % arbitrary initial values
>> % first method. Not efficient!
>> F = zeros(length(x),length(y));
>> for i = 1:length(x),
>> for j = 1:length(y),
>> F(i,j) = x(i)*exp(-x(i)^2-y(j)^2);
>> end
>> end
>> % second method. Better!
>> [X Y] = meshgrid(x,y);
>> F = X.*exp(-X.^2-Y.^2);
\end{lstlisting}
In this example we can also use the fact that $F$ is a separable function of $x$ and $y$, to further simplify the calculations. Using $F(x,y)=\big(xe^{-x^2}\big)e^{-y^2}$ we can write
\begin{lstlisting}
>> F = (x .* exp(-x.^2))' * exp(-y.^2); % Efficient!
\end{lstlisting}
\end{example}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\subsection{Profiling the program speed}
We can use the \texttt{tic} and \texttt{toc} functions or the \texttt{cputime} function to find the exact execution time of a codes:
\begin{lstlisting}
>> tic % start timer
>> procedure1; % the procedure
>> toc % stop timer
>> % Or
>> t = cputime;
>> procedure2; % the procedure
>> dt = cputime - t
\end{lstlisting}
For more detailed information on a code (including all the functions and its sub-functions), the \texttt{profile} function can be used, which gives a complete report of the program timing. This information can help one find the bottlenecks of the code and write them more efficiently or even implement them using MEX-functions, which are explained in the next section. All we need to do for profiling a program is:
\begin{lstlisting}
>> profile on
>> procedure; % a function or m-file which you want to profile
>> profile off
>> profile viewer
\end{lstlisting}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\section{Linking MATLAB with external components}
We can run OS commands directly from the MATLAB command line:
\begin{lstlisting}
>> ! dir
>> ! autoexec.bat
\end{lstlisting}
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\subsubsection{Calling MATLAB routines from C/C++}
MATLAB functions can be executed from a C/C++ program. This is done by the MATLAB Engine library, which may be called from other programs. The corresponding examples can be found in the \texttt{<MATLAB>$\backslash$extern$\backslash$} directory. In summary one needs to transfer data between MATLAB and C/C++ and to be able to execute the MATLAB functions. The MATLAB Engine has several different routines for data transfer and function calls from C/C++.
MATLAB functions may also be converted to stand-alone programs or dynamically linked libraries (DLLs). One can use the MATLAB COM Builder (\texttt{comtool}) for this purpose. Take a look at MATLAB's documents for further details. You can also design a graphical interface for your codes using the \texttt{guide} tool.
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\subsubsection{Calling C routines from MATLAB}
By now we have presented some general guidelines for optimizing MATLAB codes. Now suppose that we have already performed all the possible optimizations, but the program is still slow, which is common in time-consuming simulations or in real-time applications. A solution that can speed-up a program up to an order of ten times, is to rewrite the bottlenecks of the codes in C. This can be done in MATLAB by using MEX-files, which stand for MATLAB Executables.
There is of course another reason for using MEX-files. We might already have many efficient codes written in C/C++ that we do not want to rewrite in MATLAB. All we have to do is to make a MEX-file interface of the source codes and call them from MATLAB.
Of course, we should note that MEX-files should not be overused, because MATLAB is a high-level programming environment for rapid system design and prototyping and one should ideally avoid going into low-level implementation details.
MEX-files are in fact DLLs made of C/C++, which can be executed by MATLAB. Every C MEX-file consists of the four following elements:
\begin{enumerate}
\item \texttt{\#include "mex.h"}
\item \texttt{mexFunction}
\item \texttt{mxArray}
\item API functions
\end{enumerate}
The \texttt{mexFunction} is the gateway to the DLL, which is called by MATLAB. In C, \texttt{mexFunction} always has the following form:
\begin{lstlisting}
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]);
\end{lstlisting}
where \texttt{nlhs} and \texttt{nrhs} are the number of outputs and inputs to the function, respectively. These two integers are equivalent with the \texttt{nargout} and \texttt{nargin} built-ins in MATLAB functions. \texttt{plhs} and \texttt{prhs} are arrays of pointers to \texttt{mxArray}.
\texttt{mxArray} is a structure representing MATLAB arrays in C. All data-types are an \texttt{mxArray} structure, containing the MATLAB variable name, its dimensions, its data-type, and whether it is a real variable or a complex one. The real and imaginary parts may be accessed by the \texttt{.pr} and \texttt{.pi} fields.
There are several functions in the mex library for sending, receiving, and processing \texttt{mxArray} data. MEX-files also have the ability of loading variables directly from the caller function or the base workspace of MATLAB. Note that MATLAB functions may also be directly called from MEX-files:
\begin{lstlisting}
mexCallMATLAB(nlhs,plhs,nrhs,prhs,"MATLAB Function Name");
\end{lstlisting}
This will however reduce the speed efficiency of MEX-files due to the overhead of calling MATLAB routines and the required data transfer.
The stages of generating MEX-file DLLs from an existing MEX-file is as follows:
\begin{enumerate}
\item C compiler selection by running \texttt{mex -setup}. MEX-files may be compiled using any C compiler. %%An ANSI C compiler called \texttt{lcc} is included with the MATLAB package; but this compiler can not compile C++ codes.
\item MEX-file DLL generation, by calling the mex command as follows:
\begin{lstlisting}
>> mex example.c
>> % or
>> mex example.c objfile.obj ex1.c libfile.lib
\end{lstlisting}
As you see, the \texttt{mex} command can also take multiple C-files and pre-compiled objects and libraries.
\item calling the MEX-file from MATLAB:
\begin{lstlisting}
>> example([1 2],1:10);
\end{lstlisting}
\end{enumerate}
If you are using Visual Studio or similar packages, you can use the \texttt{dumpbin.exe} program to check the contents of the DLLs produced by MATLAB. An examples of sliding median filters and trimmed mean filters implemented in C and converted into a MATLAB MEX file can be found in the open-source electrophysiological toolbox (OSET) \citep{OSET3.14}.
%/////////////////////////////////////////////////////////////////////////////////////////////////////////
\flushleft
\bibliographystyle{abbrvnat}
\bibliography{bibliography}
\nocite{*}
\end{document}