<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Performance &#8211; Undocumented Matlab</title>
	<atom:link href="https://undocumentedmatlab.com/articles/tag/performance/feed" rel="self" type="application/rss+xml" />
	<link>https://undocumentedmatlab.com</link>
	<description>Professional Matlab consulting, development and training</description>
	<lastBuildDate>Mon, 17 Aug 2020 08:29:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.2</generator>
	<item>
		<title>Speeding-up builtin Matlab functions – part 3</title>
		<link>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-3?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=speeding-up-builtin-matlab-functions-part-3</link>
					<comments>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-3#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Mon, 06 Apr 2020 20:44:07 +0000</pubDate>
				<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Stock Matlab function]]></category>
		<category><![CDATA[Toolbox]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pure Matlab]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=11059</guid>

					<description><![CDATA[<p>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example.  </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-3">Speeding-up builtin Matlab functions – part 3</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 2">Speeding-up builtin Matlab functions &#8211; part 2 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 1">Speeding-up builtin Matlab functions &#8211; part 1 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/callback-functions-performance" rel="bookmark" title="Callback functions performance">Callback functions performance </a> <small>Using anonymous functions in Matlab callbacks can be very painful for performance. Today's article explains how this can be avoided. ...</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>A recurring theme in this website is that despite a common misperception, builtin Matlab functions are typically coded for maximal accuracy and correctness, but not necessarily best run-time performance. Despite this, we can often identify and fix the hotspots in these functions and use a modified faster variant in our code. I have shown multiple examples for this in various posts (<a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1" target="_blank">example1</a>, <a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2" target="_blank">example2</a>, <a href="https://undocumentedmatlab.com/articles/tag/performance" target="_blank">many others</a>). </p>
<p>Today I will show another example, this time speeding up the <i><b>mvksdensity</b></i> (multi-variate kernel probability density estimate) function, part of the Statistics toolbox since R2016a. You will need Matlab R2016a or newer with the Stats Toolbox to recreate my results, but the general methodology and conclusions hold well for numerous other builtin Matlab functions that may be slowing down your Matlab program. In my specific problem, this function was used to compute the probability density-function (PDF) over a 1024&#215;1024 data mesh. </p>
<p>The builtin <i><b>mvksdensity</b></i> function took <b>76 seconds</b> to run on my machine; I got this down to <b>13 seconds</b>, a <b>6x speedup</b>, without compromising accuracy. Here&#8217;s how I did this:</p>
<h3 id="preparation">Preparing the work files</h3>
<p>While we could in theory modify Matlab&#8217;s installed m-files if we have administrator privileges, doing this is not a good idea for several reasons. Instead, we should copy and rename the relevant internal files to our work folder, and only modify our local copies.</p>
<p>To see where the builtin files are located, we can use the <b><i>which</i></b> function:</p>
<pre lang="matlab">
>> which('mvksdensity')
C:\Program Files\Matlab\R2020a\toolbox\stats\stats\mvksdensity.m
</pre>
<p>In our case, we copy <i>\toolbox\stats\stats\mvksdensity.m</i> as <i>mvksdensity_.m</i> to our work folder, replace the function name at the top of the file from <code>mvksdensity</code> to <code>mvksdensity_</code>, and modify our code to call <i><b>mvksdensity_</b></i> rather than <i><b>mvksdensity</b></i>. </p>
<p>If we run our code, we get an error telling us that Matlab can&#8217;t find the <i><b>statkscompute</b></i> function (in line #107 of our <i>mvksdensity_.m</i>). So we find <i>statkscompute.m</i> in the <i>\toolbox\stats\stats\private\</i> folder, copy it as <i>statkscompute_.m</i> to our work folder, rename its function name (at the top of the file) to <code>statkscompute_</code>, and modify our <i>mvksdensity_.m</i> to call <i><b>statkscompute_</b></i> rather than <i><b>statkscompute</b></i>:</p>
<pre lang="matlab">[fout,xout,u] = statkscompute_(ftype,xi,xispecified,npoints,u,L,U,weight,cutoff,...</pre>
<p>We now repeat the process over and over, until we have all copied all the necessary internal files for the program to run. In our case, it tuns out that in addition to <i>mvksdensity.m</i> and <i>statkscompute.m</i>, we also need to copy <i>statkskernelinfo.m</i>. </p>
<p>Finally, we check that the numeric results using the copied files are exactly the same as from the builtin method, just to be on the safe side that we have not left out some forgotten internal file.</p>
<p>Now that we have copied these 3 files, in practice all our attentions will be focused on the <i>dokernel</i> sub-function inside <i>statkscompute_.m</i>, since the profiling report (below) indicates that this is where all of the run-time is spent.</p>
<h3 id="identify">Identifying the hotspots</h3>
<p>Now we run the code through the Matlab Profiler, using the &#8220;Run and Time&#8221; button in the Matlab Editor, or <i><b>profile on/report</b></i> in the Matlab console (Command Window). The results show that 99.8% of <i><b>mvksdensity</b></i>&#8216;s time was spent in the internal <i>dokernel</i> function, 75% of which was spent in self-time (meaning code lines within <i>dokernel</i>):<br />
<center><figure style="width: 640px" class="wp-caption aligncenter"><img fetchpriority="high" decoding="async" src="https://undocumentedmatlab.com/images/mvksdensity-profile1.png" alt="Initial profiling results - pretty slow..." title="Initial profiling results - pretty slow..." width="640" height="280" /><figcaption class="wp-caption-text">Initial profiling results - pretty slow...</figcaption></figure></center></p>
<p>Let&#8217;s drill into <i>dokernel</i> and see where the problems are:<br />
<center><figure style="width: 764px" class="wp-caption aligncenter"><img decoding="async" src="https://undocumentedmatlab.com/images/mvksdensity-profile2.png" alt="Initial dokernel profiling results" title="Initial dokernel profiling results" width="764" height="464" /><figcaption class="wp-caption-text">Initial dokernel profiling results</figcaption></figure></center></p>
<h3 id="normal">Evaluating the normal kernel distribution</h3>
<p>We can immediately see from the profiling results that a single line (#386) in <i>statkscompute_.m</i> is responsible for nearly 40% of the total run-time:</p>
<pre lang="matlab">fk = feval(kernel,z);</pre>
<p>In this case, <code>kernel</code> is a function handle to the normal-distribution function in <i>\stats\private\statkskernelinfo&gt;normal</i>, which is evaluated 1,488,094 times. Using <i><b>feval</b></i> incurs an overhead, as can be seen by the difference in run-times: line #386 takes 29.55 secs, whereas the <b><i>normal</i></b> function evaluations only take 18.53 secs. In fact, if you drill into the <b><i>normal</i></b> function in the profiling report, you&#8217;ll see that the actual code line that computes the normal distribution only takes 8-9 seconds &#8211; all the rest (~20 secs, or ~30% of the total) is totally redundant function-call overhead. Let&#8217;s try to remove this overhead by calling the <code>kernel</code> function directly:</p>
<pre lang="matlab">fk = kernel(z);</pre>
<p>Now that we have a local copy of <i>statkscompute_.m</i>, we can safely modify the <i>dokernel</i> sub-function, specifically line #386 as explained above. It turns out that just bypassing the <i><b>feval</b></i> call and using the function-handle directly does not improve the run-time (decrease the function-call overhead) significantly, at least on recent Matlab releases (it has a greater effect on old Matlab releases, but that&#8217;s a side-issue). </p>
<p>We now recognize that the program only evaluates the normal-distribution kernel, which is the default kernel. So let&#8217;s handle this special case by inlining the kernel&#8217;s one-line code (from <i>statkskernelinfo_.m</i>) directly (note how we move the condition outside of the loop, so that it doesn&#8217;t get recomputed 1 million times):</p>
<pre lang="matlab" highlight="2,31-32,34">
...
isKernelNormal = strcmp(char(kernel),'normal');  % line #357 
for i = 1:m
    Idx = true(n,1);
    cdfIdx = true(n,1);
    cdfIdx_allBelow = true(n,1);
    for j = 1:d
        dist = txi(i,j) - ty(:,j);
        currentIdx = abs(dist) <= halfwidth(j);
        Idx = currentIdx &#038; Idx; % pdf boundary
        if iscdf
            currentCdfIdx = dist >= -halfwidth(j);
            cdfIdx = currentCdfIdx & cdfIdx; %cdf boundary1, equal or below the query point in all dimension
            currentCdfIdx_below = dist - halfwidth(j) > 0;                   
            cdfIdx_allBelow = currentCdfIdx_below & cdfIdx_allBelow; %cdf boundary2, below the pdf lower boundary in all dimension
        end
    end
    if ~iscdf
        nearby = index(Idx);
    else
        nearby = index((Idx|cdfIdx)&(~cdfIdx_allBelow));
    end
    if ~isempty(nearby)
        ftemp = ones(length(nearby),1);
        for k =1:d
            z = (txi(i,k) - ty(nearby,k))./u(k);
            if reflectionPDF
                zleft  = (txi(i,k) + ty(nearby,k)-2*L(k))./u(k);
                zright = (txi(i,k) + ty(nearby,k)-2*U(k))./u(k);
                fk = kernel(z) + kernel(zleft) + kernel(zright);  % old: =feval()+...
            elseif isKernelNormal
                fk = exp(-0.5 * (z.*z)) ./ sqrt(2*pi);
            else
                fk = kernel(z);  %old: =feval(kernel,z);
            end
            if needUntransform(k)
                fk = untransform_f(fk,L(k),U(k),xi(i,k));
            end
            ftemp = ftemp.*fk;
        end
        f(i) = weight(nearby) * ftemp;
    end
    if iscdf && any(cdfIdx_allBelow)
        f(i) = f(i) + sum(weight(cdfIdx_allBelow));
    end
end
...
</pre>
<p>This reduced the kernel evaluation run-time from ~30 secs down to 8-9 secs. Not only did we remove the direct function-call overhead, but also the overheads associated with calling a sub-function in a different m-file. The total run-time is now down to <b>45-55</b> seconds (expect some fluctuations from run to run). Not a bad start.</p>
<h3 id="loop-bottom">Main loop &#8211; bottom part</h3>
<p>Now let&#8217;s take a fresh look at the profiling report, and focus separately on the bottom and top parts of the main loop, which you can see above. We start with the bottom part, since we already messed with it in our fix to the kernel evaluation:</p>
<p><center><figure style="width: 550px" class="wp-caption aligncenter"><img decoding="async" src="https://undocumentedmatlab.com/images/mvksdensity-profile3.png" alt="Profiling results for bottom part of the main loop" title="Profiling results for bottom part of the main loop" width="550" height="348" /><figcaption class="wp-caption-text">Profiling results for bottom part of the main loop</figcaption></figure></center></p>
<p>The first thing we note is that there&#8217;s an inner loop that runs d=2 times (d is set in line #127 of <i>mvksdensity_.m</i> &#8211; it is the input mesh&#8217;s dimensionality, and also the number of columns in the <code>txi</code> data matrix). We can easily vectorize this inner loop, but we take care to do this only for the special case of d==2 and when some other special conditions occur. </p>
<p>In addition, we hoist outside of the main loop anything that we can (such as the constant exponential power, and the weight multiplication when it is constant [which is typical]), so that they are only computed once instead of 1 million times:</p>
<pre lang="matlab" highlight="3-8,12-16,34-37,39,45-50">
...
isKernelNormal = strcmp(char(kernel),'normal');
anyNeedTransform = any(needUntransform);
uniqueWeights = unique(weight);
isSingleWeight = ~iscdf && numel(uniqueWeights)==1;
isSpecialCase1 = isKernelNormal && ~reflectionPDF && ~anyNeedTransform && d==2;
expFactor = -0.5 ./ (u.*u)';
TWO_PI = 2*pi;
for i = 1:m
    ...
    if ~isempty(nearby)
        if isSpecialCase1
            z = txi(i,:) - ty(nearby,:);
            ftemp = exp((z.*z) * expFactor);
        else
            ftemp = 1;  % no need for the slow ones()
            for k = 1:d
                z = (txi(i,k) - ty(nearby,k)) ./ u(k);
                if reflectionPDF
                    zleft  = (txi(i,k) + ty(nearby,k)-2*L(k)) ./ u(k);
                    zright = (txi(i,k) + ty(nearby,k)-2*U(k)) ./ u(k);
                    fk = kernel(z) + kernel(zleft) + kernel(zright);  % old: =feval()+...
                elseif isKernelNormal
                    fk = exp(-0.5 * (z.*z)) ./ sqrt(TWO_PI);
                else
                    fk = kernel(z);  % old: =feval(kernel,z)
                end
                if needUntransform(k)
                    fk = untransform_f(fk,L(k),U(k),xi(i,k));
                end
                ftemp = ftemp.*fk;
            end
            ftemp = ftemp * TWO_PI;
        end
        if isSingleWeight
            f(i) = sum(ftemp);
        else
            f(i) = weight(nearby) * ftemp;
        end
    end
    if iscdf && any(cdfIdx_allBelow)
        f(i) = f(i) + sum(weight(cdfIdx_allBelow));
    end
end
if isSingleWeight
    f = f * uniqueWeights;
end
if isKernelNormal && ~reflectionPDF
    f = f ./ TWO_PI;
end
...
</pre>
<p>This brings the run-time down to <b>31-32 secs</b>. Not bad at all, but we can still do much better:</p>
<h3 id="loop-top">Main loop &#8211; top part</h3>
<p>Now let&#8217;s take a look at the profiling report&#8217;s top part of the main loop:</p>
<p><center><figure style="width: 550px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/mvksdensity-profile4.png" alt="Profiling results for top part of the main loop" title="Profiling results for to part of the main loop" width="550" height="414" /><figcaption class="wp-caption-text">Profiling results for top part of the main loop</figcaption></figure></center></p>
<p>Again we note is that there&#8217;s an inner loop that runs d=2 times, which we can again easily vectorize. In addition, we note the unnecessary repeated initializations of the <code>true(n,1)</code> vector, which can easily be hoisted outside the loop:</p>
<pre lang="matlab" highlight="2-3,5-13,30">
...
TRUE_N = true(n,1);
isSpecialCase2 = ~iscdf && d==2;
for i = 1:m
    if isSpecialCase2
        dist = txi(i,:) - ty;
        currentIdx = abs(dist) <= halfwidth;
        currentIdx = currentIdx(:,1) &#038; currentIdx(:,2);
        nearby = index(currentIdx);
    else
        Idx = TRUE_N;
        cdfIdx = TRUE_N;
        cdfIdx_allBelow = TRUE_N;
        for j = 1:d
            dist = txi(i,j) - ty(:,j);
            currentIdx = abs(dist) <= halfwidth(j);
            Idx = currentIdx &#038; Idx; % pdf boundary
            if iscdf
                currentCdfIdx = dist >= -halfwidth(j);
                cdfIdx = currentCdfIdx & cdfIdx; % cdf boundary1, equal or below the query point in all dimension
                currentCdfIdx_below = dist - halfwidth(j) > 0;
                cdfIdx_allBelow = currentCdfIdx_below & cdfIdx_allBelow; %cdf boundary2, below the pdf lower boundary in all dimension
            end
        end
        if ~iscdf
            nearby = index(Idx);
        else
            nearby = index((Idx|cdfIdx)&(~cdfIdx_allBelow));
        end
    end
    if ~isempty(nearby)
        ...
</pre>
<p>This brings the run-time down to <b>24 seconds</b>. </p>
<p>We next note that instead of using numeric indexes to compute the <code>nearby</code> vector, we could use faster logical indexes:</p>
<pre lang="matlab" highlight="2,9,26,28,31">
...
%index = (1:n)';  % this is no longer needed
TRUE_N = true(n,1);
isSpecialCase2 = ~iscdf && d==2;
for i = 1:m
    if isSpecialCase2
        dist = txi(i,:) - ty;
        currentIdx = abs(dist) <= halfwidth;
        nearby = currentIdx(:,1) &#038; currentIdx(:,2);
    else
        Idx = TRUE_N;
        cdfIdx = TRUE_N;
        cdfIdx_allBelow = TRUE_N;
        for j = 1:d
            dist = txi(i,j) - ty(:,j);
            currentIdx = abs(dist) <= halfwidth(j);
            Idx = currentIdx &#038; Idx; % pdf boundary
            if iscdf
                currentCdfIdx = dist >= -halfwidth(j);
                cdfIdx = currentCdfIdx & cdfIdx; % cdf boundary1, equal or below the query point in all dimension
                currentCdfIdx_below = dist - halfwidth(j) > 0;
                cdfIdx_allBelow = currentCdfIdx_below & cdfIdx_allBelow; %cdf boundary2, below the pdf lower boundary in all dimension
            end
        end
        if ~iscdf
            nearby = Idx;  % not index(Idx)
        else
            nearby = (Idx|cdfIdx) & ~cdfIdx_allBelow;  % no index()
        end
    end
    if any(nearby)
        ...
</pre>
<p>This brings the run-time down to <b>20 seconds</b>. </p>
<p>We now note that the main loop runs m=1,048,576 (=1024&#215;1024) times over all rows of <code>txi</code>. This is expected, since the loop runs over all the elements of a 1024&#215;1024 mesh grid, which are reshaped as a 1,048,576-element column array at some earlier point in the processing, resulting in a m-by-d matrix (1,048,576-by-2 in our specific case). This information helps us, because we know that there are only 1024 unique values in each of the two columns of <code>txi</code>. Therefore, instead of computing the &#8220;closeness&#8221; metric (which leads to the <code>nearby</code> vector) for all 1,048,576 x 2 values of <code>txi</code>, we calculate separate vectors for each of the 1024 unique values in each of its 2 columns, and then merge the results inside the loop:</p>
<pre lang="matlab" highlight="3-10,13-15">
...
isSpecialCase2 = ~iscdf && d==2;
if isSpecialCase2
    [unique1Vals, ~, unique1Idx] = unique(txi(:,1));
    [unique2Vals, ~, unique2Idx] = unique(txi(:,2));
    dist1 = unique1Vals' - ty(:,1);
    dist2 = unique2Vals' - ty(:,2);
    currentIdx1 = abs(dist1) <= halfwidth(1);
    currentIdx2 = abs(dist2) <= halfwidth(2);
end
for i = 1:m
    if isSpecialCase2
        idx1 = unique1Idx(i);
        idx2 = unique2Idx(i);
        nearby = currentIdx1(:,idx1) &#038; currentIdx2(:,idx2);
    else
        ...
</pre>
<p>This brings the run-time down to <b>13 seconds</b>, a total speedup of almost ~6x compared to the original version. Not bad at all.</p>
<p>For reference, here's a profiling summary of the <i>dokernel</i> function again, showing the updated performance hotspots:</p>
<p><center><figure style="width: 550px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/mvksdensity-profile5.png" alt="Profiling results after optimization" title="Profiling results after optimization" width="550" height="201" /><figcaption class="wp-caption-text">Profiling results after optimization</figcaption></figure></center></p>
<p>The 2 vectorized code lines in the bottom part of the main loop now account for 72% of the remaining run-time:</p>
<pre lang="matlab" highlight="4-5">
    ...
    if ~isempty(nearby)
        if isSpecialCase1
            z = txi(i,:) - ty(nearby,:);
            ftemp = exp((z.*z) * expFactor);
        else
            ...
</pre>
<p>If I had the inclination, speeding up these two code lines would be the next logical step, but I stop at this point. Interested readers could pick up this challenge and post a solution in the comments section below. I haven't tried it myself, so perhaps there's no easy way to improve this. Then again, perhaps the answer is just around the corner - if you don't try, you'll never know...</p>
<h3 id="resolution">Data density/resolution</h3>
<p>So far, all the optimization I made have not affected code accuracy, generality or resolution. This is always the best approach if you have some spare coding time on your hands.</p>
<p>In some cases, we might have a deep understanding of our domain problem to be able to sacrifice a bit of accuracy in return for run-time speedup. In our case, we identify the main loop over 1024x1024 elements as the deciding factor in the run-time. If we reduce the grid-size by 50% in each dimension (i.e. 512x512), the run-time decreases by an additional factor of almost 4, down to <b>~3.5 seconds</b>, which is what we would have expected since the main loop size has decreased 4 times in size. While this reduces the results resolution/accuracy, we got a 4x speedup in a fraction of the time that it took to make all the coding changes above. </p>
<p>Different situations may require different approaches: in some cases we cannot sacrifice accuracy/resolution, and must spend time to improve the algorithm implementation; in other cases coding time is at a premium and we can sacrifice accuracy/resolution; and in other cases still, we could use a combination of both approaches.</p>
<h3 id="conclusions">Conclusions</h3>
<p>Matlab is composed of thousands of internal functions. Each and every one of these functions was meticulously developed and tested by engineers, who are after all only human. Whereas supreme emphasis is always placed with Matlab functions on their accuracy, run-time performance often takes a back-seat. Make no mistake about this: code accuracy is almost always more important than speed, so I’m not complaining about the current state of affairs.</p>
<p>But when we run into a specific run-time problem in our Matlab program, we should not despair if we see that built-in functions cause slowdown. We can try to avoid calling those functions (for example, by reducing the number of invocations, or decreasing the data resolution, or limiting the target accuracy, etc.), or we could optimize these functions in our own local copy, as I have shown today. There are multiple techniques that we could employ to improve the run time. Just use the profiler and keep an open mind about alternative speed-up mechanisms, and you’d be half-way there. For ideas about the multitude of different speedup techniques that you could use in Matlab, see my book <b><a href="https://undocumentedmatlab.com/books/matlab-performance" target="_blank">Accelerating Matlab Performance</a></b>.</p>
<p><a href="https://undocumentedmatlab.com/consulting" target="_blank">Let me know</a> if you’d like me to assist with your Matlab project, either developing it from scratch or improving your existing code, or just training you in how to improve your Matlab code’s run-time/robustness/usability/appearance.</p>
<p>In the meantime, Happy Easter/Passover everyone, and stay healthy!</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-3">Speeding-up builtin Matlab functions – part 3</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 2">Speeding-up builtin Matlab functions &#8211; part 2 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 1">Speeding-up builtin Matlab functions &#8211; part 1 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/callback-functions-performance" rel="bookmark" title="Callback functions performance">Callback functions performance </a> <small>Using anonymous functions in Matlab callbacks can be very painful for performance. Today's article explains how this can be avoided. ...</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-3/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Improving graphics interactivity</title>
		<link>https://undocumentedmatlab.com/articles/improving-graphics-interactivity?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=improving-graphics-interactivity</link>
					<comments>https://undocumentedmatlab.com/articles/improving-graphics-interactivity#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Sun, 21 Apr 2019 21:03:10 +0000</pubDate>
				<category><![CDATA[GUI]]></category>
		<category><![CDATA[Handle graphics]]></category>
		<category><![CDATA[Medium risk of breaking in future versions]]></category>
		<category><![CDATA[Stock Matlab function]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pure Matlab]]></category>
		<category><![CDATA[Toolbar]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=8723</guid>

					<description><![CDATA[<p>Matlab R2018b added default axes mouse interactivity at the expense of performance. Luckily, we can speed-up the default axes. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/improving-graphics-interactivity">Improving graphics interactivity</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-hg2-graphics-events" rel="bookmark" title="Undocumented HG2 graphics events">Undocumented HG2 graphics events </a> <small>Matlab's new HG2 graphics engine includes many new undocumented events that could be used in various ways. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/handle-graphics-behavior" rel="bookmark" title="Handle Graphics Behavior">Handle Graphics Behavior </a> <small>HG behaviors are an important aspect of Matlab graphics that enable custom control of handle functionality. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/improving-save-performance" rel="bookmark" title="Improving save performance">Improving save performance </a> <small>There are many different ways of improving Matlab's standard save function performance. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/waterloo-graphics" rel="bookmark" title="Waterloo graphics">Waterloo graphics </a> <small>Waterloo is an open-source library that can significantly improve Matlab GUI. ...</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>Matlab release R2018b added the concept of <a href="https://undocumentedmatlab.com/articles/reverting-axes-controls-in-figure-toolbar" target="_blank">axes-specific toolbars</a> and default <a href="https://www.mathworks.com/help/matlab/creating_plots/control-axes-interactions.html" rel="nofollow" target="_blank">axes mouse interactivity</a>. <span class="alignright"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/speedometer4d_200x200.gif" alt="Accelerating MATLAB Performance" title="Accelerating MATLAB Performance" width="200" height="200" /></span> Plain 2D plot axes have the following default interactions enabled by default: <a href="https://www.mathworks.com/help/matlab/ref/matlab.graphics.interaction.interactions.paninteraction.html" rel="nofollow" target="_blank">PanInteraction</a>, <a href="https://www.mathworks.com/help/matlab/ref/matlab.graphics.interaction.interactions.zoominteraction.html" rel="nofollow" target="_blank">ZoomInteraction</a>, <a href="https://www.mathworks.com/help/matlab/ref/matlab.graphics.interaction.interactions.datatipinteraction.html" rel="nofollow" target="_blank">DataTipInteraction</a> and <a href="https://www.mathworks.com/help/matlab/ref/matlab.graphics.interaction.interactions.rulerpaninteraction.html" rel="nofollow" target="_blank">RulerPanInteraction</a>.</p>
<p>Unfortunately, I find that while the default interactions set is much more useful than the non-interactive default axes behavior in R2018a and earlier, it could still be improved in two important ways:</p>
<ol>
<li><b>Performance</b> &#8211; Matlab&#8217;s builtin Interaction objects are very inefficient. In cases of multiple overlapping axes (which is very common in multi-tab GUIs or cases of various types of axes), instead of processing events for just the top visible axes, they process all the enabled interactions for *all* axes (including non-visible ones!). This is particularly problematic with the default DataTipInteraction &#8211; it includes a <code>Linger</code> object whose apparent purpose is to detect when the mouse lingers for enough time on top of a chart object, and displays a data-tip in such cases. Its internal code is both inefficient and processed multiple times (for each of the axes), as can be seen via a profiling session.</li>
<li><b>Usability</b> &#8211; In my experience, <a href="https://www.mathworks.com/help/matlab/ref/matlab.graphics.interaction.interactions.regionzoominteraction.html" rel="nofollow" target="_blank">RegionZoomInteraction</a> (which enables defining a region zoom-box via click-&#038;-drag) is usually much more useful than PanInteraction for most plot types. ZoomInteraction, which is enabled by default only enables zooming-in and -out using the mouse-wheel, which is much less useful and more cumbersome to use than RegionZoomInteraction. The panning functionality can still be accessed interactively with the mouse by dragging the X and Y rulers (ticks) to each side.</li>
</ol>
<p>For these reasons, I typically use the following function whenever I create new axes, to replace the default sluggish DataTipInteraction and PanInteraction with RegionZoomInteraction:<br />
<span id="more-10306"></span></p>
<pre lang="matlab">
function axDefaultCreateFcn(hAxes, ~)
    try
        hAxes.Interactions = [zoomInteraction regionZoomInteraction rulerPanInteraction];
        hAxes.Toolbar = [];
    catch
        % ignore - old Matlab release
    end
end
</pre>
<p>The purpose of these two axes property changes shall become apparent below.<br />
This function can either be called directly (<code>axDefaultCreateFcn(hAxes</code>), or as part of the containing figure&#8217;s creation script to ensure than any axes created in this figure has this fix applied:</p>
<pre lang="matlab">
set(hFig,'defaultAxesCreateFcn',@axDefaultCreateFcn);
</pre>
<h3 id="testing">Test setup</h3>
<p><figure style="width: 268px" class="wp-caption alignright"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/Axes_Interactivity.png" alt="Figure with default axes toolbar and interactivity" title="Figure with default axes toolbar and interactivity" width="268" height="200" /><figcaption class="wp-caption-text">Figure with default axes toolbar and interactivity</figcaption></figure> To test the changes, let&#8217;s prepare a figure with 10 tabs, with 10 overlapping panels and a single axes in each tab:</p>
<pre lang="matlab">
hFig = figure('Pos',[10,10,400,300]);
hTabGroup = uitabgroup(hFig);
for iTab = 1 : 10
    hTab = uitab(hTabGroup, 'title',num2str(iTab));
    hPanel = uipanel(hTab);
    for iPanel = 1 : 10
        hPanel = uipanel(hPanel);
    end
    hAxes(iTab) = axes(hPanel); %see MLint note below
    plot(hAxes(iTab),1:5,'-ob');
end
drawnow
</pre>
<p style="padding-left: 20px; margin-top: -15px;"><i><font size=-1>p.s. &#8211; there&#8217;s a incorrect MLint (Code Analyzer) warning in line 9 about the call to axes(hPanel) being inefficient in a loop. Apparently, MLint incorrectly parses this function call as a request to make the axes in-focus, rather than as a request to create the axes in the specified hPanel parent container. We can safely ignore this warning.</font></i></p>
<p>Now let&#8217;s create a run-time test script that simulates 2000 mouse movements using <a href="https://undocumentedmatlab.com/articles/gui-automation-robot" target="_blank">java.awt.Robot</a>:</p>
<pre lang="matlab">
tic
monitorPos = get(0,'MonitorPositions');
y0 = monitorPos(1,4) - 200;
robot = java.awt.Robot;
for iEvent = 1 : 2000
    robot.mouseMove(150, y0+mod(iEvent,100));
    drawnow
end
toc
</pre>
<p>This takes ~45 seconds to run on my laptop: ~23ms per mouse movement on average, with noticeable &#8220;linger&#8221; when the mouse pointer is near the plotted data line. Note that this figure is extremely simplistic &#8211; In a real-life program, the mouse events processing lag the mouse movements, making the GUI far more sluggish than the same GUI on R2018a or earlier. In fact, in one of my more complex GUIs, the entire GUI and Matlab itself came to a standstill that required killing the Matlab process, just by moving the mouse for several seconds.</p>
<p>Notice that at any time, only a single axes is actually visible in our test setup. The other 9 axes are not visible although their <b>Visible</b> property is <code>'on'</code>. Despite this, when the mouse moves within the figure, these other axes unnecessarily process the mouse events.</p>
<h3 id="interactions">Changing the default interactions</h3>
<p>Let&#8217;s modify the axes creation script as I mentioned above, by changing the default interactions (note the highlighted code addition):</p>
<pre lang="matlab" highlight="11">
hFig = figure('Pos',[10,10,400,300]);
hTabGroup = uitabgroup(hFig);
for iTab = 1 : 10
    hTab = uitab(hTabGroup, 'title',num2str(iTab));
    hPanel = uipanel(hTab);
    for iPanel = 1 : 10
        hPanel = uipanel(hPanel);
    end
    hAxes(iTab) = axes(hPanel);
    plot(hAxes(iTab),1:5,'-ob');
    hAxes(iTab).Interactions = [zoomInteraction regionZoomInteraction rulerPanInteraction];
end
drawnow
</pre>
<p>The test script now takes only 12 seconds to run &#8211; 4x faster than the default and yet IMHO with better interactivity (using RegionZoomInteraction).</p>
<h3 id="Toolbar">Effects of the axes toolbar</h3>
<p>The axes-specific toolbar, another innovation of R2018b, does not just have interactivity aspects, which are by themselves <a href="https://undocumentedmatlab.com/articles/reverting-axes-controls-in-figure-toolbar" target="_blank">much-contested</a>. A much less discussed aspect of the axes toolbar is that it degrades the overall performance of axes. The reason is that the axes toolbar&#8217;s transparency, visibility, background color and contents continuously update whenever the mouse moves within the axes area.</p>
<p>Since we have set up the default interactivity to a more-usable set above, and since we can replace the axes toolbar with figure-level toolbar controls, we can simply delete the axes-level toolbars for even more-improved performance:</p>
<pre lang="matlab" highlight="12">
hFig = figure('Pos',[10,10,400,300]);
hTabGroup = uitabgroup(hFig);
for iTab = 1 : 10
    hTab = uitab(hTabGroup, 'title',num2str(iTab));
    hPanel = uipanel(hTab);
    for iPanel = 1 : 10
        hPanel = uipanel(hPanel);
    end
    hAxes(iTab) = axes(hPanel);
    plot(hAxes(iTab),1:5,'-ob');
    hAxes(iTab).Interactions = [zoomInteraction regionZoomInteraction rulerPanInteraction];
    hAxes(iTab).Toolbar = [];
end
drawnow
</pre>
<p>This brings the test script&#8217;s run-time down to 6 seconds &#8211; <b>7x faster than the default run-time</b>. At ~3ms per mouse event, the GUI is now as performant and snippy as in R2018a, even with the new interactive mouse actions of R2018b active.</p>
<h3 id="Conclusions">Conclusions</h3>
<p>MathWorks definitely did not intend for this slow-down aspect, but it is an unfortunate by-product of the choice to auto-enable DataTipInteraction and of its sub-optimal implementation. Perhaps this side-effect was never noticed by MathWorks because the testing scripts probably had only a few axes in a very simple figure &#8211; in such a case the performance lags are very small and might have slipped under the radar. But I assume that many real-life complex GUIs will display significant lags in R2018b and newer Matlab releases, compared to R2018a and earlier releases. I assume that such users will be surprised/dismayed to discover that in R2018b their GUI not only interacts differently but also runs slower, although the program code has not changed.</p>
<p>One of the common claims that I often hear against using undocumented Matlab features is that the program might break in some future Matlab release that would not support some of these features. But users certainly do not expect that their programs might break in new Matlab releases when they only use documented features, as in this case. IMHO, this case (and others over the years) demonstrates that using undocumented features is usually not much riskier than using the standard documented features with regards to future compatibility, making the risk/reward ratio more favorable. In fact, of the ~400 posts that I have published in the past decade (this blog is already 10 years old, time flies&#8230;), very few tips no longer work in the latest Matlab release. When such forward compatibility issues do arise, whether with fully-documented or undocumented features, we can often find workarounds as I have shown above.</p>
<p>If your Matlab program could use a performance boost, I would be happy to assist making your program faster and more responsive. Don&#8217;t hesitate to reach out to me for a consulting quote.</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/improving-graphics-interactivity">Improving graphics interactivity</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-hg2-graphics-events" rel="bookmark" title="Undocumented HG2 graphics events">Undocumented HG2 graphics events </a> <small>Matlab's new HG2 graphics engine includes many new undocumented events that could be used in various ways. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/handle-graphics-behavior" rel="bookmark" title="Handle Graphics Behavior">Handle Graphics Behavior </a> <small>HG behaviors are an important aspect of Matlab graphics that enable custom control of handle functionality. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/improving-save-performance" rel="bookmark" title="Improving save performance">Improving save performance </a> <small>There are many different ways of improving Matlab's standard save function performance. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/waterloo-graphics" rel="bookmark" title="Waterloo graphics">Waterloo graphics </a> <small>Waterloo is an open-source library that can significantly improve Matlab GUI. ...</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/improving-graphics-interactivity/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Multi-threaded Mex</title>
		<link>https://undocumentedmatlab.com/articles/multi-threaded-mex?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=multi-threaded-mex</link>
					<comments>https://undocumentedmatlab.com/articles/multi-threaded-mex#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Wed, 18 Jul 2018 14:56:44 +0000</pubDate>
				<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Mex]]></category>
		<category><![CDATA[Undocumented feature]]></category>
		<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=7771</guid>

					<description><![CDATA[<p>Tips for creating and debugging multi-threaded Mex functions are discussed. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/multi-threaded-mex">Multi-threaded Mex</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part4" rel="bookmark" title="Explicit multi-threading in Matlab part 4">Explicit multi-threading in Matlab part 4 </a> <small>Matlab performance can be improved by employing timer objects and spawning external processes. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part3" rel="bookmark" title="Explicit multi-threading in Matlab part 3">Explicit multi-threading in Matlab part 3 </a> <small>Matlab performance can be improved by employing POSIX threads in C/C++ code. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part2" rel="bookmark" title="Explicit multi-threading in Matlab part 2">Explicit multi-threading in Matlab part 2 </a> <small>Matlab performance can be improved by employing .Net (C#, VB, F# or C++) threads. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/multi-line-uitable-column-headers" rel="bookmark" title="Multi-line uitable column headers">Multi-line uitable column headers </a> <small>Matlab uitables can present long column headers in multiple lines, for improved readability. ...</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>I was recently asked by a consulting client to help speed up a Matlab process. <span class="alignright"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/speedometer4d_200x200.gif" alt="Accelerating MATLAB Performance" title="Accelerating MATLAB Performance" width="200" height="200" /></span> Quite often there are various ways to improve the run-time, and in this particular case it turned out that the best option was to convert the core Matlab processing loop into a multi-threaded Mex function, while keeping the rest (vast majority of program code) in easy-to-maintain Matlab. This resulted in a 160x speedup (25 secs => 0.16 secs). Some of this speedup is attributed to C-code being faster in general than Matlab, another part is due to the multi-threading, and another due to <a href="/articles/matlab-mex-in-place-editing" target="_blank">in-place data manipulations</a> that avoid costly memory access and re-allocations.<br />
In today&#8217;s post I will share some of the insights relating to this MEX conversion, which could be adapted for many other similar use-cases. Additional Matlab speed-up techniques can be found in other <a href="/articles/tag/performance" target="_blank">performance-related posts</a> on this website, as well in my book <a href="/books/matlab-performance" target="_blank"><b>Accelerating MATLAB Performance</b></a>.<br />
There are quite a few online resources about creating Mex files, so I will not focus on this aspect. I&#8217;ll assume that the reader is already familiar with the concept of using Mex functions, which are simply dynamically-linked libraries that have a predefined entry-function syntax and predefined platform-specific extension. Instead, I&#8217;ll focus on how to create and debug a multi-threaded Mex function, so that it runs in parallel on all CPU cores.<br />
The benefit of multi-<i>threading</i> is that threads are very light-weight objects, that have minimal performance and memory overheads. This contrasts to multi-<i>tasking</i>, which is what the Parallel Computing Toolbox currently does: launches duplicate copies of the entire Matlab engine process (&#8220;headless workers&#8221;) and then manages and coordinates the tasks to split up the processing work. Multi-tasking should be avoided wherever we can employ light-weight multi-threading instead. Unfortunately, Matlab does not currently have the ability to explicitly multi-thread Matlab code. But we can still use explicit multi-threading by invoking code in other languages, as I&#8217;ve already shown for <a href="/articles/explicit-multi-threading-in-matlab-part1" target="_blank">Java</a>, <a href="/articles/explicit-multi-threading-in-matlab-part2" target="_blank">C# (and .NET in general)</a>, and <a href="/articles/explicit-multi-threading-in-matlab-part3" target="_blank">C/C++</a>. Today&#8217;s article will expand on the latter post (the one about C/C++ multi-threading), by showing a general framework for making a multi-threaded C-based Mex function.<br />
<span id="more-7771"></span><br />
There are several alternative implementation of threads. On non-Windows machines, POSIX threads (&#8220;pthreads&#8221;) are a de-facto standard; on Windows, which pthreads can still be used, they generally use native Windows threads under the hood, and we can use these native threads directly.<br />
I have uploaded a file called <a href="https://www.mathworks.com/matlabcentral/fileexchange/68237-max_in_place-example-of-multi-threaded-mex-function" rel="nofollow" target="_blank">max_in_place</a> to the Matlab File Exchange. This function serves as an example showing a generic multi-threaded Mex function. A compiled version of this Mex file for Win64 is also included in the File Exchange entry, and you can run it directly on a Win64 machine.<br />
The usage in Matlab is as follows (note how <code>matrix1</code> is updated in-place):</p>
<pre lang="matlab">
>> matrix1 = rand(4)
matrix1 =
      0.89092      0.14929      0.81428      0.19664
      0.95929      0.25751      0.24352      0.25108
      0.54722      0.84072      0.92926      0.61604
      0.13862      0.25428      0.34998      0.47329
>> matrix2 = rand(4)
matrix2 =
      0.35166      0.91719      0.38045      0.53081
      0.83083      0.28584      0.56782      0.77917
      0.58526       0.7572     0.075854      0.93401
      0.54972      0.75373      0.05395      0.12991
>> max_in_place(matrix1, matrix2)
>> matrix1
matrix1 =
      0.89092      0.91719      0.81428      0.53081
      0.95929      0.28584      0.56782      0.77917
      0.58526      0.84072      0.92926      0.93401
      0.54972      0.75373      0.34998      0.47329
</pre>
<h3 id="source-code">Source code and discussion</h3>
<p>The pseudo-code for the MEX function is as follows:</p>
<pre lang="text">
mexFunction():
   validate the input/output args
   quick bail-out if empty inputs
   get the number of threads N from Matlab's maxNumCompThreads function
   if N == 1
       run main_loop directly
   else
       split input matrix #1 into N index blocks
       assign start/end index for each thread
       create and launch N new threads that run main_loop
       wait for all N threads to complete
       free the allocated memory resources
   end
</pre>
<p>Here&#8217;s the core source-code of this function, which was adapted from original work by <a href="https://www.mathworks.com/matlabcentral/profile/authors/1097878-dirk-jan-kroon" rel="nofollow" target="_blank">Dirk-Jan Kroon</a>:</p>
<pre lang="cpp">
/*====================================================================
 *
 * max_in_place.c  updates a data matrix in-place with the max value
 *                 of the matrix and a 2nd matrix of the same size
 *
 * The calling syntax is:
 *
 *		max_in_place(matrix1, matrix2)
 *
 * matrix1 will be updated with the maximal values from corresponding
 * indices of the 2 matrices
 *
 * Both inputs must be double 2D real non-sparse matrices of same size
 *
 * Yair Altman 2018-07-18
 * https://UndocumentedMatlab.com/articles/multi-threaded-mex
 *
 * Adapted from original work by Dirk-Jan Kroon
 * http://mathworks.com/matlabcentral/profile/authors/1097878-dirk-jan-kroon
 *
 *==================================================================*/
#include <math.h>
#include "mex.h"
/* undef needed for LCC compiler */
#undef EXTERN_C
#ifdef _WIN32
    #include <windows.h>
    #include <process.h>
#else
    #include <pthread.h>
#endif
/* Input Arguments */
#define	hMatrix1	prhs[0]
#define	hMatrix2	prhs[1]
/* Macros */
#if !defined(MAX)
#define	MIN(A, B)	((A) < (B) ? (A) : (B))
#endif
/* Main processing loop function */
void main_loop(const mxArray *prhs[], int startIdx, int endIdx)
{
    /* Assign pointers to the various parameters */
    double *p1 = mxGetPr(hMatrix1);
    double *p2 = mxGetPr(hMatrix2);
    /* Loop through all matrix coordinates */
    for (int idx=startIdx; idx<=endIdx; idx++)
    {
        /* Update hMatrix1 with the maximal value of hMatrix1,hMatrix2 */
        if (p1[idx] < p2[idx]) {
            p1[idx] = p2[idx];
        }
    }
}
/* Computation function in threads */
#ifdef _WIN32
  unsigned __stdcall thread_func(void *ThreadArgs_) {
#else
  void thread_func(void *ThreadArgs_) {
#endif
    double **ThreadArgs = ThreadArgs_;  /* void* => double** */
    const mxArray** prhs = (const mxArray**) ThreadArgs[0];
    int ThreadID = (int) ThreadArgs[1][0];
    int startIdx = (int) ThreadArgs[2][0];
    int endIdx   = (int) ThreadArgs[3][0];
    /*mexPrintf("Starting thread #%d: idx=%d:%d\n", ThreadID, startIdx, endIdx); */
    /* Run the main processing function */
    main_loop(prhs, startIdx, endIdx);
    /* Explicit end thread, helps to ensure proper recovery of resources allocated for the thread */
    #ifdef _WIN32
        _endthreadex( 0 );
        return 0;
    #else
        pthread_exit(NULL);
    #endif
}
/* validateInputs function here... */
/* Main entry function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    /* Validate the inputs */
    validateInputs(nlhs, plhs, nrhs, prhs);
    /* Quick bail-out in the trivial case of empty inputs */
    if (mxIsEmpty(hMatrix1))  return;
    /* Get the number of threads from the Matlab engine (maxNumCompThreads) */
    mxArray *matlabCallOut[1] = {0};
    mxArray *matlabCallIn[1]  = {0};
    mexCallMATLAB(1, matlabCallOut, 0, matlabCallIn, "maxNumCompThreads");
    double *Nthreadsd = mxGetPr(matlabCallOut[0]);
    int Nthreads = (int) Nthreadsd[0];
    /* Get the number of elements to process */
    size_t n1 = mxGetNumberOfElements(hMatrix1);
    if (Nthreads == 1) {
        /* Process the inputs directly (not via a thread) */
        main_loop(prhs, 0, n1-1);
    } else {  /* multi-threaded */
        /* Allocate memory for handles of worker threads */
        #ifdef _WIN32
            HANDLE    *ThreadList = (HANDLE*)   malloc(Nthreads*sizeof(HANDLE));
        #else
            pthread_t *ThreadList = (pthread_t*)malloc(Nthreads*sizeof(pthread_t));
        #endif
        /* Allocate memory for the thread arguments (attributes) */
        double **ThreadID, **ThreadStartIdx, **ThreadEndIdx, ***ThreadArgs;
        double *ThreadID1, *ThreadStartIdx1, *ThreadEndIdx1, **ThreadArgs1;
        ThreadID       = (double **) malloc( Nthreads* sizeof(double *) );
        ThreadStartIdx = (double **) malloc( Nthreads* sizeof(double *) );
        ThreadEndIdx   = (double **) malloc( Nthreads* sizeof(double *) );
        ThreadArgs     = (double ***)malloc( Nthreads* sizeof(double **) );
        /* Launch the requested number of threads */
        int i;
        int threadBlockSize = ceil( ((double)n1) / Nthreads );
        for (i=0; i<nthreads; i++)
        {
            /* Create thread ID */
            ThreadID1 = (double *)malloc( 1* sizeof(double) );
            ThreadID1[0] = i;
            ThreadID[i] = ThreadID1;
            /* Compute start/end indexes for this thread */
            ThreadStartIdx1 = (double *) malloc( sizeof(double) );
            ThreadStartIdx1[0] = i * threadBlockSize;
            ThreadStartIdx[i] = ThreadStartIdx1;
            ThreadEndIdx1 = (double *) malloc( sizeof(double) );
            ThreadEndIdx1[0] = MIN((i+1)*threadBlockSize, n1) - 1;
            ThreadEndIdx[i] = ThreadEndIdx1;
            /* Prepare thread input args */
            ThreadArgs1 = (double **) malloc( 4* sizeof(double*) );
            ThreadArgs1[0] = (double *) prhs;
            ThreadArgs1[1] = ThreadID[i];
            ThreadArgs1[2] = ThreadStartIdx[i];
            ThreadArgs1[3] = ThreadEndIdx[i];
            ThreadArgs[i] = ThreadArgs1;
            /* Launch the thread with its associated args */
            #ifdef _WIN32
                ThreadList[i] = (HANDLE)_beginthreadex(NULL, 0, &#038;thread_func, ThreadArgs[i], 0, NULL);
            #else
                pthread_create ((pthread_t*)&#038;ThreadList[i], NULL, (void *) &#038;thread_func, ThreadArgs[i]);
            #endif
        }
        /* Wait for all the treads to finish working */
        #ifdef _WIN32
            for (i=0; i<nthreads; i++) { WaitForSingleObject(ThreadList[i], INFINITE); }
            for (i=0; i<nthreads; i++) { CloseHandle( ThreadList[i] ); }
        #else
            for (i=0; i<nthreads; i++) { pthread_join(ThreadList[i],NULL); }
        #endif
        /* Free the memory resources allocated for the threads */
        for (i=0; i<nthreads; i++)
        {
            free(ThreadArgs[i]);
            free(ThreadID[i]);
            free(ThreadStartIdx[i]);
            free(ThreadEndIdx[i]);
        }
        free(ThreadArgs);
        free(ThreadID );
        free(ThreadStartIdx);
        free(ThreadEndIdx);
        free(ThreadList);
    }
    return;
}
</pre>
<p>This file also includes a <i>validateInputs</i> function. I did not include it in the code snippet above for brevity; you can read it directly in the FEX entry (<i>max_in_place.c</i>). This function checks that there are exactly 0 output and 2 input args, that the input args are real non-sparse matrices and that they have the same number of elements.<br />
Note that the threads run a generic <i>thread_func</i> function, which in turn runs the <i>main_loop</i> function with the thread's specified <code>startIndex</code>, <code>endIndex</code> values. When this function completes, the thread ends itself explicitly, to ensure resource cleanup.<br />
Also note how the thread code is using pthreads on non-Windows (<code>!defined(_WIN32)</code>) machines, and native Windows threads otherwise. This means that the same MEX source-code could be used on all Matlab platforms.<br />
The important thing to note about this framework is that we no longer need to worry about the thread plumbing. If we wish to adapt this code for any other processing, we just need to modify the <i>main_loop</i> function with the new processing logic. In addition, you may wish to modify the <i>validateInputs</i> function based on your new setup of input/output args.<br />
A few caveats:</p>
<ul>
<li>On Windows machines with R2017b or older, we simply compile using <code>mex max_in_place.c</code>; on non-Windows we might need to add the <code>–lpthread</code> flag to link the pthreads library, depending on your specific compiler.</li>
<li>On R2018a or newer on all platforms, due to MEX's new <a href="https://www.mathworks.com/help/matlab/matlab_external/matlab-support-for-interleaved-complex.html" rel="nofollow" target="_blank">interleaved-complex memory format</a>, we would need to compile with the <code>-R2017b</code> flag if we wish to use <i><a href="https://www.mathworks.com/help/matlab/apiref/mxgetpr.html" rel="nofollow" target="_blank">mexGetPr</a></i>, as in the sample code above (in R2018a's new data model, the corresponding function is <i><a href="https://www.mathworks.com/help/matlab/apiref/mxgetdoubles.html" rel="nofollow" target="_blank">mxGetDoubles</a></i>). Note that updating data in-place becomes more difficult with the new MEX API, so if you want to preserve the performance boost that in-place data manipulation provides, it may be better to stick with the legacy data memory model.</li>
<li>The sample code above splits the data between the threads based on the first input matrix's size. Instead, you may consider sending to the MEX function the loop indexes as extra input args, and then splitting those up between the threads.</li>
<li>In this specific implementation of <i>max_in_place</i>, I have updated the data locations directly. This is generally discouraged and risky, because it conflicts with Matlab's standard Copy-on-Write mechanism. For example, if we assign the input to any other Matlab variable(s) before calling <i>max_in_place</i>, then that other variable(s) will also get their data updated. If we do not want this side-effect, we should <a href="/articles/matlab-mex-in-place-editing" target="_blank">mxUnshareArray</a> the input matrix1, and return the resulting matrix as an output of the MEX function (<code>plhs[0]</code>).</li>
</ul>
<h3 id="tips">Speed-up tips</h3>
<p>The core logic in the specific case that I was asked to optimize was something similar to this:</p>
<pre lang="text">
main_process:
    initialize output matrix
    loop z over all slices in a 3D data matrix
        temp_data = data(:,:,z);
        temp_data = process(temp_data);
        output = max(output, temp_data);
    end z loop
</pre>
<p>The initial speed-up attempt was naturally focused on the <code>process</code> and <code>max</code> functions. Converting them to a MEX function improved the speed by a factor of ~8, but the resulting run-time (4-5 secs) was still too slow for real-time use. The reason that we did not see a larger speed-up was, I believe, due to several reasons:</p>
<ul>
<li><code>temp_data</code> was small enough such that the overheads associated with creating and then disposing separate threads were significant compared to the processing time of each thread.</li>
<li><code>temp_data</code> was small enough such that each thread processed a relatively small portion of the memory, in contrast to single-threaded processing that accesses memory in larger blocks, more efficiently.</li>
<li>In each iteration of the z loop, the overheads associated with calling the MEX function, handling input variables and validation, creating/disposing threads, and allocating/deallocating memory for <code>temp_data</code>, were repeatedly paid.</li>
</ul>
<p>So, while the profiling result showed that 98% of the time was spent in the MEX function (which would seem to indicate that not much additional speedup can be achieved), in fact the MEX function was under-performing because of the inefficiencies involved in repeatedly creating threads to process small data chunks. It turned out that running in single-thread mode was actually somewhat faster than multi-threaded mode.<br />
I then moved the entire z loop (entire <code>main_process</code>) into the MEX function, where the threads were split to process separate adjacent blocks of z slices (i.e. different blocks of the z loop). This way, the MEX function was called, the inputs validated, and threads created/disposed only once for the entire process, making this overhead negligible compared to each thread's processing time. Moreover, each thread now processed the entire <code>temp_data</code> belonging to its z slice, so memory access was more efficient, reducing the memory I/O wait time and improving the overall processing time. Additional benefits were due to the fact that some variables could be reused within each thread across loop iterations, minimizing memory allocations and deallocations. The overall effect was to reduce the total run-time down to ~0.16 secs, a 160x speedup compared to the original (25 secs). As my client said: "<i>You sped up [the application] from practically useless to clinically useful</i>."<br />
The lesson: try to minimize MEX invocation and thread creation/disposal overheads, and let the threads process as large adjacent memory blocks as possible.</p>
<h3 id="debugging">Debugging MEX files</h3>
<p>When debugging multi-threaded MEX functions, I find that it's often easier to run the function in single-threaded mode to debug the core logic, and once this is ready we can switch back multi-threading. This can easily be done by setting the number of threads outside the MEX function using Matlab's builtin <i><b><a href="https://www.mathworks.com/help/matlab/ref/maxnumcompthreads.html" rel="nofollow" target="_blank">maxNumCompThreads</a></b></i> function:</p>
<pre lang="matlab">
Nthreads = maxNumCompThreads(1);  % temporarily use only 1 thread for debugging
max_in_place(matrix1, matrix2);
maxNumCompThreads(Nthreads);      % restore previous value
%maxNumCompThreads('automatic');  % alternative
</pre>
<p>Once debugging is done and the MEX function works properly, we should remove the <i><b>maxNumCompThreads</b></i> calls, so that the MEX function will use the regular number of Matlab computational threads, which should be the same as the number of cores: <a href="/articles/undocumented-feature-function" target="_blank">feature('numCores')</a>.<br />
I typically like to use Eclipse as my IDE for non-Matlab code (Java, C/C++ etc.). Unfortunately, there's a problem attaching Eclipse to Matlab processes (which is necessary for interactive MEX debugging) if you're using any recent (post-2015) version of MinGW and Eclipse. This problem is due to a <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=474311" rel="nofollow" target="_blank">known Eclipse bug</a>, as user Lithe <a href="https://www.mathworks.com/matlabcentral/answers/241291-how-to-debug-mex-file-compiled-with-mingw64-and-g-flags#comment_461391" rel="nofollow" target="_blank">pointed out</a>. The workaround is to install an old version of MinGW, *in addition* to your existing MinGW version. <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=474311#c15" rel="nofollow" target="_blank">Reportedly</a>, only versions <a href="https://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/Previous/1.1309.0/" rel="nofollow" target="_blank">4.9.1 or older</a> of MinGW include gdb 7.8 (which is still supported by Eclipse), whereas newer versions of MinGW include a newer gdb that is not supported. Download and install such an old MinGW version in a separate folder from your more-modern compiler. Don't update your MEX to use the older MinGW - just tell Eclipse to use the version of gdb in the old MinGW bin/ folder when you set up a debug configuration for debugging your MEX files.<br />
Once you have a compatible gdb, and ask Eclipse to attach to a process, the processes list will finally appear (it won't with an incompatible gdb). Use <code><a href="/articles/undocumented-feature-function" target="_blank">feature('getPID')</a></code> to get your Matlab process ID, which can then used to attach to the relevant process in the Eclipse Attach-to-process window. For example, if your Matlab's PID is 4321, then the Matlab process will be called "Program - 4321" in Eclipse's processes list.<br />
I wish that MathWorks would update their <a href="https://www.mathworks.com/matlabcentral/answers/241291-how-to-debug-mex-file-compiled-with-mingw64-and-g-flags" rel="nofollow" target="_blank">official Answer</a> and their <a href="https://www.mathworks.com/matlabcentral/fileexchange/52848-matlab-support-for-mingw-w64-c-c-compiler" rel="nofollow" target="_blank">MinGW support package on File Exchange</a> to include this information, because without it debugging on Eclipse becomes impossible. Eclipse is so powerful, easy-to-use and ubiquitous that it's a shame for most users not to be able to work with it just because the workarounds above are not readily explained.<br />
N.B. If you don't like Eclipse, you can also use Visual Studio Code (VS Code), as Andy Campbell <a href="https://blogs.mathworks.com/developer/2018/06/19/mex-debugging-vscode" rel="nofollow" target="_blank">recently explained</a> in the MathWorks Developers' blog.</p>
<h3 id="consulting">Consulting</h3>
<p>Do you have any Matlab code that could use a bit (or a lot) of speeding-up? If so, please <a href="/consulting#request" target="_blank">contact me</a> for a private consulting offer. I can't promise to speed up your code by a similar factor of 160x, but you never know...</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/multi-threaded-mex">Multi-threaded Mex</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part4" rel="bookmark" title="Explicit multi-threading in Matlab part 4">Explicit multi-threading in Matlab part 4 </a> <small>Matlab performance can be improved by employing timer objects and spawning external processes. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part3" rel="bookmark" title="Explicit multi-threading in Matlab part 3">Explicit multi-threading in Matlab part 3 </a> <small>Matlab performance can be improved by employing POSIX threads in C/C++ code. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part2" rel="bookmark" title="Explicit multi-threading in Matlab part 2">Explicit multi-threading in Matlab part 2 </a> <small>Matlab performance can be improved by employing .Net (C#, VB, F# or C++) threads. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/multi-line-uitable-column-headers" rel="bookmark" title="Multi-line uitable column headers">Multi-line uitable column headers </a> <small>Matlab uitables can present long column headers in multiple lines, for improved readability. ...</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/multi-threaded-mex/feed</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Blocked wait with timeout for asynchronous events</title>
		<link>https://undocumentedmatlab.com/articles/blocked-wait-with-timeout-for-asynchronous-events?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=blocked-wait-with-timeout-for-asynchronous-events</link>
					<comments>https://undocumentedmatlab.com/articles/blocked-wait-with-timeout-for-asynchronous-events#respond</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Sun, 13 May 2018 20:22:08 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Listeners]]></category>
		<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Memory]]></category>
		<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=7620</guid>

					<description><![CDATA[<p>It is easy to convert asynchronous (streaming) events into a blocked wait in Matlab. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/blocked-wait-with-timeout-for-asynchronous-events">Blocked wait with timeout for asynchronous events</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/waiting-for-asynchronous-events" rel="bookmark" title="Waiting for asynchronous events">Waiting for asynchronous events </a> <small>The Matlab waitfor function can be used to wait for asynchronous Java/ActiveX events, as well as with timeouts. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/udd-events-and-listeners" rel="bookmark" title="UDD Events and Listeners">UDD Events and Listeners </a> <small>UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events" rel="bookmark" title="Matlab callbacks for Java events">Matlab callbacks for Java events </a> <small>Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/detecting-window-focus-events" rel="bookmark" title="Detecting window focus events">Detecting window focus events </a> <small>Matlab does not have any documented method to detect window focus events (gain/loss). This article describes an undocumented way to detect such events....</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>Readers of this website may have noticed that I have recently added an <a href="/iqml" rel="nofollow" target="_blank">IQML section</a> to the website&#8217;s top menu bar. IQML is a software connector that connects Matlab to DTN&#8217;s IQFeed, a financial data-feed of live and historic market data. IQFeed, like most other data-feed providers, sends its data in asynchronous messages, which need to be processed one at a time by the receiving client program (Matlab in this case). I wanted IQML to provide users with two complementary modes of operation:<br />
<span class="alignright"><a href="/iqml" rel="nofollow" target="_blank"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/IQML.png" title="IQML's IQFeed-Matlab connectivity" alt="IQML's IQFeed-Matlab connectivity" width="426" height="213"/></a></span></p>
<ul>
<li><b>Streaming</b> (asynchronous, non-blocking) &#8211; incoming server data is processed by internal callback functions in the background, and is made available for the user to query at any later time.</li>
<li><b>Blocking</b> (synchronously waiting for data) &#8211; in this case, the main Matlab processing flows waits until the data arrives, or until the specified timeout period has passed &#8211; whichever comes first.</li>
</ul>
<p>Implementing streaming mode is relatively simple in general &#8211; all we need to do is ensure that the underlying connector object passes the incoming server messages to the relevant Matlab function for processing, and ensure that the user has some external way to access this processed data in Matlab memory (in practice making the connector object pass incoming data messages as Matlab callback events may be non-trivial, but that&#8217;s a separate matter &#8211; <a href="/articles/matlab-callbacks-for-java-events" target="_blank">read here</a> for details).<br />
In today&#8217;s article I&#8217;ll explain how we can implement a blocking mode in Matlab. It may sound difficult but it turns out to be relatively simple.<br />
I had several requirements/criteria for my blocked-wait implementation:</p>
<ol>
<li><b>Compatibility</b> &#8211; It had to work on all Matlab platforms, and all Matlab releases in the past decade (which rules out using Microsoft Dot-NET objects)</li>
<li><b>Ease-of-use</b> &#8211; It had to work out-of-the-box, with no additional installation/configuration (which ruled out using Perl/Python objects), and had to use a simple interface function</li>
<li><b>Timeout</b> &#8211; It had to implement a timed-wait, and had to be able to tell whether the program proceeded due to a timeout, or because the expected event has arrived</li>
<li><b>Performance</b> &#8211; It had to have minimal performance overhead</li>
</ol>
<p><span id="more-7620"></span></p>
<h3 id="basic">The basic idea</h3>
<p>The basic idea is to use Matlab&#8217;s builtin <i><b>waitfor</b></i>, as I explained in <a href="/articles/waiting-for-asynchronous-events" target="_blank">another post</a> back in 2012. If our underlying connector object has some settable boolean property (e.g., <code>Done</code>) then we can set this property in our event callback, and then <code>waitfor(object,'Done')</code>. The timeout mechanism is implemented using a dedicated timer object, as follows:</p>
<pre lang="matlab">
% Wait for data updates to complete (isDone = false if timeout, true if event has arrived)
function isDone = waitForDone(object, timeout)
    % Initialize: timeout flag = false
    object.setDone(false);
    % Create and start the separate timeout timer thread
    hTimer = timer('TimerFcn',@(h,e)object.setDone(true), 'StartDelay',timeout);
    start(hTimer);
    % Wait for the object property to change or for timeout, whichever comes first
    waitfor(object,'Done');
    % waitfor is over - either because of timeout or because the data changed
    % To determine which, check whether the timer callback was activated
    isDone = isvalid(hTimer) && hTimer.TasksExecuted == 0;
    % Delete the timer object
    try stop(hTimer);   catch, end
    try delete(hTimer); catch, end
    % Return the flag indicating whether or not timeout was reached
end  % waitForDone
</pre>
<p>where the event callback is responsible for invoking <code>object.setDone(true)</code> when the server data arrives. The usage would then be similar to this:</p>
<pre lang="matlab">
requestDataFromServer();
if isBlockingMode
   % Blocking mode - wait for data or timeout (whichever comes first)
   isDone = waitForDone(object, 10.0);  % wait up to 10 secs for data to arrive
   if ~isDone  % indicates a timeout
      fprintf(2, 'No server data has arrived within the specified timeout period!\n')
   end
else
   % Non-blocking (streaming) mode - continue with regular processing
end
</pre>
<h3 id="generic">Using a stand-alone generic signaling object</h3>
<p>But what can we do if we don&#8217;t have such a <code>Done</code> property in our underlying object, or if we do not have programmatic access to it?<br />
We could create a new non-visible figure and then <i><b>waitfor</b></i> one of its properties (e.g. <code>Resize</code>). The property would be initialized to <code>'off'</code>, and within both the event and timer callbacks we would set it to <code>'on'</code>, and then <code>waitfor(hFigure,'Resize','on')</code>. However, figures, even if non-visible, are quite heavy objects in terms of both memory, UI resources, and performance.<br />
It would be preferable to use a much lighter-weight object, as long as it abides by the other criteria above. Luckily, there are numerous such objects in Java, which is bundled in every Matlab since 2000, on every Matlab platform. As long as we choose a small Java object that has existed forever, we should be fine. For example, we could use a simple <code>javax.swing.JButton</code> and its boolean property <code>Enabled</code>:</p>
<pre lang="matlab">
hSemaphore = handle(javax.swing.JButton);  % waitfor() expects a handle() object, not a "naked" Java reference
% Wait for data updates to complete (isDone = false if timeout, true if event has arrived)
function isDone = waitForDone(hSemaphore, timeout)
    % Initialize: timeout flag = false
    hSemaphore.setEnabled(false);
    % Create and start the separate timeout timer thread
    hTimer = timer('TimerFcn',@(h,e)hSemaphore.setEnabled(true), 'StartDelay',timeout);
    start(hTimer);
    % Wait for the object property to change or for timeout, whichever comes first
    waitfor(hSemaphore,'Enabled');
    % waitfor is over - either because of timeout or because the data changed
    % To determine which, check whether the timer callback was activated
    isDone = isvalid(hTimer) && hTimer.TasksExecuted == 0;
    % Delete the timer object
    try stop(hTimer);   catch, end
    try delete(hTimer); catch, end
    % Return the flag indicating whether or not timeout was reached
end  % waitForDone
</pre>
<p>In this implementation, we would need to pass the <code>hSemaphore</code> object handle to the event callback, so that it would be able to invoke <code>hSemaphore.setEnabled(true)</code> when the server data has arrived.<br />
Under the hood, note that <code>Enabled</code> is not a true &#8220;property&#8221; of <code>javax.swing.JButton</code>, but rather exposes two simple public getter/setter methods (<i>setEnabled()</i> and <i>isEnabled()</i>), which Matlab interprets as a &#8220;property&#8221;. For all intents and purposes, in our Matlab code we can treat <code>Enabled</code> as a property of <code>javax.swing.JButton</code>, including its use by Matlab&#8217;s builtin <i><b>waitfor</b></i> function.<br />
There is a light overhead to this: on my laptop the <i><b>waitfor</b></i> function returns ~20 mSecs after the invocation of <code>hSemaphore.setEnabled(true)</code> in the timer or event callback &#8211; in many cases this overhead is negligible compared to the networking latencies for the blocked data request. When event reactivity is of utmost importance, users can always use streaming (non-blocking) mode, and process the incoming data events immediately in a callback.<br />
Of course, it would have been best if MathWorks would add a timeout option and return value to Matlab&#8217;s builtin <i><b>waitfor</b></i> function, similar to my <code>waitForDone</code> function &#8211; this would significantly simplify the code above. But until this happens, you can use <code>waitForDone</code> pretty-much as-is. I have used similar combinations of blocking and streaming modes with multiple other connectors that I implemented over the years (Interactive Brokers, CQG, Bloomberg and Reuters for example), and the bottom line is that it actually works well in practice.<br />
<a href="/consulting" target="_blank">Let me know</a> if you&#8217;d like me to assist with your own Matlab project or data connector, either developing it from scratch or improving your existing code. I will be visiting Boston and New York in early June and would be happy to meet you in person to discuss your specific needs.</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/blocked-wait-with-timeout-for-asynchronous-events">Blocked wait with timeout for asynchronous events</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/waiting-for-asynchronous-events" rel="bookmark" title="Waiting for asynchronous events">Waiting for asynchronous events </a> <small>The Matlab waitfor function can be used to wait for asynchronous Java/ActiveX events, as well as with timeouts. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/udd-events-and-listeners" rel="bookmark" title="UDD Events and Listeners">UDD Events and Listeners </a> <small>UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events" rel="bookmark" title="Matlab callbacks for Java events">Matlab callbacks for Java events </a> <small>Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/detecting-window-focus-events" rel="bookmark" title="Detecting window focus events">Detecting window focus events </a> <small>Matlab does not have any documented method to detect window focus events (gain/loss). This article describes an undocumented way to detect such events....</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/blocked-wait-with-timeout-for-asynchronous-events/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Speeding-up builtin Matlab functions &#8211; part 2</title>
		<link>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=speeding-up-builtin-matlab-functions-part-2</link>
					<comments>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Sun, 06 May 2018 16:26:19 +0000</pubDate>
				<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Stock Matlab function]]></category>
		<category><![CDATA[Toolbox]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pure Matlab]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=7533</guid>

					<description><![CDATA[<p>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2">Speeding-up builtin Matlab functions &#8211; part 2</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 1">Speeding-up builtin Matlab functions &#8211; part 1 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/callback-functions-performance" rel="bookmark" title="Callback functions performance">Callback functions performance </a> <small>Using anonymous functions in Matlab callbacks can be very painful for performance. Today's article explains how this can be avoided. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-mouse-pointer-functions" rel="bookmark" title="Undocumented mouse pointer functions">Undocumented mouse pointer functions </a> <small>Matlab contains several well-documented functions and properties for the mouse pointer. However, some very-useful functions have remained undocumented and unsupported. This post details their usage....</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>Last week <a href="/articles/speeding-up-builtin-matlab-functions-part-1" target="_blank">I showed</a> how we can speed-up built-in Matlab functions, by creating local copies of the relevant m-files and then optimizing them for improved speed using a variety of techniques.<span class="alignright"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/speedometer3b3_200x200.gif" alt="Accelerating MATLAB Performance" title="Accelerating MATLAB Performance" width="200" height="200" /></span> Today I will show another example of such speed-up, this time of the Financial Toolbox&#8217;s <i><b><a href="https://www.mathworks.com/help/finance/maxdrawdown.html" rel="nofollow" target="_blank">maxdrawdown</a></b></i> function, which is <a href="https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp" rel="nofollow" target="_blank">widely used</a> to estimate the relative risk of a trading strategy or asset. One might think that such a basic indicator would be optimized for speed, but experience shows otherwise. In fact, this function turned out to be the main run-time performance hotspot for one of my clients. The vast majority of his code was optimized for speed, and he naturally assumed that the built-in Matlab functions were optimized as well, but this was not the case. Fortunately, I was able to create an equivalent version that was 30-40 times faster (!), and my client remains a loyal Matlab fan.<br />
In today&#8217;s post I will show how I achieved this speed-up, using different methods than the ones I showed last week. A combination of these techniques can be used in a wide range of other Matlab functions. Additional speed-up techniques can be found in other <a href="/articles/tag/performance" target="_blank">performance-related posts</a> on this website, as well in my book <a href="/books/matlab-performance" target="_blank"><b>Accelerating MATLAB Performance</b></a>.<br />
<span id="more-7533"></span></p>
<h3 id="profiling">Profiling</h3>
<p>As I explained last week, the first step in speeding up any function is to profile its current run-time behavior using Matlab&#8217;s builtin <a href="https://www.mathworks.com/help/matlab/matlab_prog/profiling-for-improving-performance.html" rel="nofollow" target="_blank">Profiler tool</a>, which can either be started from the Matlab Editor toolstrip (&#8220;Run and Time&#8221;) or via the <a href="https://www.mathworks.com/help/matlab/ref/profile.html" rel="nofollow" target="_blank"><i><b>profile</b></i></a> function.<br />
The profile report for the client&#8217;s function showed that it had two separate performance hotspots:</p>
<ol>
<li>Code that checks the drawdown format (optional 2nd input argument) against a set of allowed formats</li>
<li>Main code section that iteratively loops over the data-series values to compute the maximal drawdown</li>
</ol>
<p>In order top optimize the code, I copied <i>%matlabroot%/toolbox/finance/finance/maxdrawdown.m</i> to a local folder on the Matlab path, renaming the file (and the function) <i>maxdrawdn</i>, in order to avoid conflict with the built-in version.</p>
<h3 id="strings">Optimizing input args pre-processing</h3>
<p>The main problem with the pre-processing of the optional format input argument is the string comparisons, which are being done even when the default format is used (which is by far the most common case). String comparison are often more expensive than numerical computations. Each comparison by itself is very short, but when <i><b>maxdrawdown</b></i> is run in a loop (as it often is), the run-time adds up.<br />
Here&#8217;s a snippet of the original code:</p>
<pre lang="matlab">
if nargin < 2 || isempty(Format)
    Format = 'return';
end
if ~ischar(Format) || size(Format,1) ~= 1
    error(message('finance:maxdrawdown:InvalidFormatType'));
end
choice = find(strncmpi(Format,{'return','arithmetic','geometric'},length(Format)));
if isempty(choice)
    error(message('finance:maxdrawdown:InvalidFormatValue'));
end
</pre>
<p>An equivalent code, which avoids any string processing in the common default case, is faster, simpler and more readable:</p>
<pre lang="matlab">
if nargin < 2 || isempty(Format)
    choice = 1;
elseif ~ischar(Format) || size(Format,1) ~= 1
    error(message('finance:maxdrawdown:InvalidFormatType'));
else
    choice = find(strncmpi(Format,{'return','arithmetic','geometric'},length(Format)));
    if isempty(choice)
        error(message('finance:maxdrawdown:InvalidFormatValue'));
    end
end
</pre>
<p>The general rule is that whenever you have a common case, you should check it first, avoiding unnecessary processing downstream. Moreover, for improved run-time performance (although not necessarily maintainability), it is generally preferable to work with numbers rather than strings (<code>choice</code> rather than <code>Format</code>, in our case).</p>
<h3 id="vectorizing">Vectorizing the main loop</h3>
<p>The main processing loop uses a very simple yet inefficient iterative loop. I assume that the code was originally developed this way in order to assist debugging and to ensure correctness, and that once it was ready nobody took the time to also optimize it for speed. It looks something like this:</p>
<pre lang="matlab">
MaxDD = zeros(1,N);
MaxDDIndex = ones(2,N);
...
if choice == 1   % 'return' format
    MaxData = Data(1,:);
    MaxIndex = ones(1,N);
    for i = 1:T
        MaxData = max(MaxData, Data(i,:));
        q = MaxData == Data(i,:);
        MaxIndex(1,q) = i;
        DD = (MaxData - Data(i,:)) ./ MaxData;
        if any(DD > MaxDD)
            p = DD > MaxDD;
            MaxDD(p) = DD(p);
            MaxDDIndex(1,p) = MaxIndex(p);
            MaxDDIndex(2,p) = i;
        end
    end
else             % 'arithmetic' or 'geometric' formats
    ...
</pre>
<p>This loop can relatively easily be vectorized, making the code much faster, and arguably also simpler, more readable, and more maintainable:</p>
<pre lang="matlab">
if choice == 3
    Data = log(Data);
end
MaxDDIndex = ones(2,N);
MaxData = cummax(Data);
MaxIndexes = find(MaxData==Data);
DD = MaxData - Data;
if choice == 1	% 'return' format
    DD = DD ./ MaxData;
end
MaxDD = cummax(DD);
MaxIndex2 = find(MaxDD==DD,1,'last');
MaxIndex1 = MaxIndexes(find(MaxIndexes<=MaxIndex2,1,'last'));
MaxDDIndex(1,:) = MaxIndex1;
MaxDDIndex(2,:) = MaxIndex2;
MaxDD = MaxDD(end,:);
</pre>
<p>Let's make a short run-time and accuracy check - we can see that we achieved a 31-fold speedup (YMMV), and received the exact same results:</p>
<pre lang="matlab">
>> data = rand(1,1e7);
>> tic, [MaxDD1, MaxDDIndex1] = maxdrawdown(data); toc  % builtin Matlab function
Elapsed time is 7.847140 seconds.
>> tic, [MaxDD2, MaxDDIndex2] = maxdrawdn(data); toc  % our optimized version
Elapsed time is 0.253130 seconds.
>> speedup = round(7.847140 / 0.253130)
speedup =
    31
>> isequal(MaxDD1,MaxDD2) && isequal(MaxDDIndex1,MaxDDIndex2)  % check accuracy
ans =
  logical
   1
</pre>
<p><b><u>Disclaimer</u></b>: The code above seems to work (quite well in fact) for a 1D data vector. You'd need to modify it a bit to handle 2D data - the returned maximal drawdown are still computed correctly but not the returned indices, due to their computation using the <i><b>find</b></i> function. This modification is left as an exercise for the reader...</p>
<h3 id="related">Related functions</h3>
<p>Very similar code could be used for the corresponding <i>maxdrawup</i> function. Although this function is used much less often than <i><b>maxdrawdown</b></i>, it is in fact widely used and very similar to <i><b>maxdrawdown</b></i>, so it is surprising that it is missing in the Financial Toolbox. Here is the corresponding code snippet:</p>
<pre lang="matlab">
% Code snippet for maxdrawup (similar to maxdrawdn)
MaxDUIndex = ones(2,N);
MinData = cummin(Data);
MinIndexes = find(MinData==Data);
DU = Data - MinData;
if choice == 1	% 'return' format
    DU = DU ./ MinData;
end
MaxDU = cummax(DU);
MaxIndex = find(MaxDD==DD,1,'last');
MinIndex = MinIndexes(find(MinIndexes<=MaxIndex,1,'last'));
MaxDUIndex(1,:) = MinIndex;
MaxDUIndex(2,:) = MaxIndex;
MaxDU = MaxDU(end,:);
</pre>
<p>Similar vectorization could be applied to the <i><b><a href="https://www.mathworks.com/help/finance/emaxdrawdown.html" rel="nofollow" target="_blank">emaxdrawdown</a></b></i> function. This too is left as an exercise for the reader...</p>
<h3 id="conclusions">Conclusions</h3>
<p>Matlab is composed of thousands of internal functions. Each and every one of these functions was meticulously developed and tested by engineers, who are after all only human. Whereas supreme emphasis is always placed with Matlab functions on their accuracy, run-time performance sometimes takes a back-seat. Make no mistake about this: code accuracy is almost always more important than speed (an exception are cases where some accuracy may be sacrificed for improved run-time performance). So I'm not complaining about the current state of affairs.<br />
But when we run into a specific run-time problem in our Matlab program, we should not despair if we see that built-in functions cause slowdown. We can try to avoid calling those functions (for example, by reducing the number of invocations, or limiting the target accuracy, etc.), or optimize these functions in our own local copy, as I've shown last week and today. There are multiple techniques that we could employ to improve the run time. Just use the profiler and keep an open mind about alternative speed-up mechanisms, and you'd be half-way there.<br />
<a href="/consulting" target="_blank">Let me know</a> if you'd like me to assist with your Matlab project, either developing it from scratch or improving your existing code, or just training you in how to improve your Matlab code's run-time/robustness/usability/appearance. I will be visiting Boston and New York in early June and would be happy to meet you in person to discuss your specific needs.</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2">Speeding-up builtin Matlab functions &#8211; part 2</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 1">Speeding-up builtin Matlab functions &#8211; part 1 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/callback-functions-performance" rel="bookmark" title="Callback functions performance">Callback functions performance </a> <small>Using anonymous functions in Matlab callbacks can be very painful for performance. Today's article explains how this can be avoided. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-mouse-pointer-functions" rel="bookmark" title="Undocumented mouse pointer functions">Undocumented mouse pointer functions </a> <small>Matlab contains several well-documented functions and properties for the mouse pointer. However, some very-useful functions have remained undocumented and unsupported. This post details their usage....</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2/feed</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>Speeding-up builtin Matlab functions &#8211; part 1</title>
		<link>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=speeding-up-builtin-matlab-functions-part-1</link>
					<comments>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Sun, 29 Apr 2018 09:46:29 +0000</pubDate>
				<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Stock Matlab function]]></category>
		<category><![CDATA[Toolbox]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pure Matlab]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=7509</guid>

					<description><![CDATA[<p>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1">Speeding-up builtin Matlab functions &#8211; part 1</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 2">Speeding-up builtin Matlab functions &#8211; part 2 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/callback-functions-performance" rel="bookmark" title="Callback functions performance">Callback functions performance </a> <small>Using anonymous functions in Matlab callbacks can be very painful for performance. Today's article explains how this can be avoided. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-mouse-pointer-functions" rel="bookmark" title="Undocumented mouse pointer functions">Undocumented mouse pointer functions </a> <small>Matlab contains several well-documented functions and properties for the mouse pointer. However, some very-useful functions have remained undocumented and unsupported. This post details their usage....</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>A client recently asked me to assist with his numeric analysis function &#8211; it took 45 minutes to run, which was unacceptable (5000 runs of ~0.55 secs each).<span class="alignright"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/speedometer4d_200x200.gif" alt="Accelerating MATLAB Performance" title="Accelerating MATLAB Performance" width="200" height="200" /></span> The code had to run in 10 minutes or less to be useful. It turns out that 99% of the run-time was taken up by Matlab&#8217;s built-in <a href="https://www.mathworks.com/help/stats/fitdist.html" rel="nofollow" target="_blank"><i><b>fitdist</b></i></a> function (part of the Statistics Toolbox), which my client was certain is already optimized for maximal performance. He therefore assumed that to get the necessary speedup he must either switch to another programming language (C/Java/Python), and/or upgrade his computer hardware at considerable expense, since parallelization was not feasible in his specific case.<br />
Luckily, I was there to assist and was able to quickly speed-up the code down to <b>7 minutes</b>, well below the required run-time. In today&#8217;s post I will show how I did this, which is relevant for a wide variety of other similar performance issues with Matlab. Many additional speed-up techniques can be found in other <a href="/articles/tag/performance" target="_blank">performance-related posts</a> on this website, as well in my book <a href="/books/matlab-performance" target="_blank"><b>Accelerating MATLAB Performance</b></a>.<br />
<span id="more-7509"></span></p>
<h3 id="profiling">Profiling</h3>
<p>The first step in speeding up any function is to profile its current run-time behavior using Matlab&#8217;s builtin <a href="https://www.mathworks.com/help/matlab/matlab_prog/profiling-for-improving-performance.html" rel="nofollow" target="_blank">Profiler tool</a>, which can either be started from the Matlab Editor toolstrip (&#8220;Run and Time&#8221;) or via the <a href="https://www.mathworks.com/help/matlab/ref/profile.html" rel="nofollow" target="_blank"><i><b>profile</b></i></a> function.<br />
The profile report for the client&#8217;s function showed that 99% of the time was spent in the Statistics Toolbox&#8217;s <i><b>fitdist</b></i> function. Drilling into this function in the profiling report, we see onion-like functions that processed input parameters, ensured data validation etc. The core processing is done inside a class that is unique to each required distribution (e.g., <code>prob.StableDistribution</code>, <code>prob.BetaDistribution</code> etc.) that is invoked within <i><b>fitdist</b></i> using an <i><b>feval</b></i> call, based on the distribution name that was specified by the user.<br />
In our specific case, the external onion layers of sanity checks were unnecessary and could be avoided. In general, I advise <i>not</i> to discard such checks, because you never know whether future uses might have a problem with outlier data or input parameters. Moreover, in the specific case of <i><b>fitdist</b></i> they take only a very minor portion of the run-time (this may be different in other cases, such as the <a href="/articles/ismembc-undocumented-helper-function" target="_blank"><i><b>ismember</b></i></a> function that I described years ago, where the sanity checks have a significant run-time impact compared to the core processing in the internal <i><b>ismembc</b></i> function).<br />
However, since we wanted to significantly improve the total run-time and this was spent within the distribution class (<code>prob.StableDistribution</code> in the case of my client), we continue to drill-down into this class to determine what can be done.<br />
It turns out that <code>prob.StableDistribution</code> basically does 3 things in its main <i>fit()</i> method:</p>
<ol>
<li>pre-process the input data (<i>prob.ToolboxFittableParametricDistribution.processFitArgs()</i> and <i>.removeCensoring()</i> methods) &#8211; this turned out to be unnecessary in my client&#8217;s data, but has little run-time impact.</li>
<li>call <i>stablefit()</i> in order to get fitting parameters &#8211; this took about half the run-time</li>
<li>call <i>stablelike()</i> in order to get likelihood data &#8211; this took about half the run-time as well</li>
<li>call <i>prob.StableDistribution.makeFitted()</i> to create a probability-distribution object returned to the caller &#8211; this also took little run-time that was not worth bothering about.</li>
</ol>
<h3 id="process">The speed-up improvement process</h3>
<p>With user-created code we could simply modify our code in-place. However, a more careful process is necessary when modifying built-in Matlab functions (either in the core Matlab distribution or in one of the toolboxes).<br />
The basic idea here is to create a side-function that would replicate the core processing of <i><b>fitdist</b></i>. This is preferable to modifying Matlab&#8217;s installation files because we could then reuse the new function in multiple computers, without having to mess around in the Matlab installation (which may not even be possible if we do not have admin privileges). Also, if we ever upgrade our Matlab we won&#8217;t need to remember to update the installed files (and obviously retest).<br />
I called the new function <i>fitdist2</i> and inside it I initially placed only the very core functionality of <i>prob.StableDistribution.fit()</i>:</p>
<pre lang="matlab">
% fitdist2 - fast replacement for fitdist(data,'stable')
% equivalent to pd = prob.StableDistribution.fit(data);
function pd = fitdist2(data)
    % Bypass pre-processing (not very important)
    [cens,freq,opt] = deal([]);
    %[data,cens,freq,opt] = prob.ToolboxFittableParametricDistribution.processFitArgs(data);
    %data = prob.ToolboxFittableParametricDistribution.removeCensoring(data,cens,freq,'stable');
    % Main processing in stablefit(), stablelike()
    params = stablefit(data,0.05,opt);
    [nll,cov] = stablelike(params,data);
    % Combine results into the returned probability distribution object
    pd = prob.StableDistribution.makeFitted(params,nll,cov,data,cens,freq);
end
</pre>
<p>If we try to run this as-is, we&#8217;d see errors because <i>stablefit()</i> and <i>stablelike()</i> are both sub-functions within <i>%matlabroot%/toolbox/stats/stats/+prob/StableDistribution.m</i>. So we copy these sub-functions (and their dependent subfunctions <i>infoMtxCal(), intMle(), tabpdf(), neglog_pdf(), stable_nloglf(), varTrans</i>) to the bottom of our <i>fitdist2.m</i> file, about 400 lines in total.<br />
We also remove places that call <i>checkargs(&#8230;)</i> since that seems to be unnecessary &#8211; if you want to keep it then add the <i>checkargs()</i> function as well.<br />
Now we re-run our code, after each speedup iteration verifying that the returned <code>pd</code> object returned by our <i>fitdist2</i> is equivalent to the original object returned by <i><b>fitdist</b></i>.</p>
<h3 id="stablefit">Speeding-up <i>stablefit()</i></h3>
<p>A new profiling run shows that the vast majority of the time in <i>stablefit()</i> is spent in two lines:</p>
<ol>
<li><code>s = load('private/StablePdfTable.mat');</code></li>
<li><code>[parmhat,~,err,output] = fminsearch(@(params)stable_nloglf(x,params),phi0,options);</code></li>
</ol>
<p>The first of these lines is reloading a static data file. The very same static data file is later reloaded in <i>stablelike()</i>. Both of these data-loads is done in every single invocation of <i><b>fitdist</b></i>, so if we have 5000 data fits, we load the same static data file 10,000 times! This is certainly not indicative of good programming practice. It would be much faster to reload the static data once into memory, and then use this cached data for the next 9,999 invocation. Since the original authors of <i>StableDistribution.m</i> seem to like single-character global variables (another bad programming practice, for multiple reasons), we&#8217;ll follow their example (added lines are highlighted):</p>
<pre lang="matlab" highlight="1-3,9">
persistent s  % this should have a more meaningful name (but at least is not global...)!
if isempty(s)
    fit_path = fileparts(which('fitdist'));
    s = load([fit_path '/private/StablePdfTable.mat']);
    a = s.a;
    b = s.b;
    xgd = s.xgd;
    p = s.p;
end
</pre>
<p>In order to speed-up the second line (that calls <b><i>fminsearch</i></b>), we can reduce the tolerances used by this function, by updating the <code>options</code> structure passed to it, so that we use tolerances of 1e-3 rather than the default 1e-6 (in our specific case this resulted in acceptable errors of ~0.1%). Specifically, we modify the code from this:</p>
<pre lang="matlab">
function [parmhat,parmci] = stablefit(x,alpha,options)
...
if nargin < 3 || isempty(options)
    options = statset('stablefit');
else
    options = statset(statset('stablefit'),options);
end
% Maximize the log-likelihood with respect to the transformed parameters
[parmhat,~,err,output] = fminsearch(@(params)stable_nloglf(x,params),phi0,options);
...
end
</pre>
<p>to this (note that the line that actually calls <b><i>fminsearch</i></b> remains unchanged):</p>
<pre lang="matlab" highlight="1,3-4,6-8">
function [parmhat,parmci] = stablefit(x,alpha,unused_options)
...
persistent options
if isempty(options)
    options = statset('stablefit');
    options.TolX   = 1e-3;
    options.TolFun = 1e-3;
    options.TolBnd = 1e-3;
end
% Maximize the log-likelihood with respect to the transformed parameters
[parmhat,~,err,output] = fminsearch(@(params)stable_nloglf(x,params),phi0,options);
...
end
</pre>
<p>The <i><b>fminsearch</b></i> internally calls <i>tabpdf()</i> repeatedly. Drilling down in the profiling report we see that it recomputes a <code>griddedInterpolant</code> object that is essentially the same for all iterations (and therefore a prime candidate for caching), and also that it uses the costly cubic interpolation rather than a more straight-forward linear interpolation:</p>
<pre lang="matlab" highlight="3-6">
function y = tabpdf(x,alpha,beta)
...
persistent G  % this should have a more meaningful name (but at least is not global...)!
if isempty(G)
    G = griddedInterpolant({b, a, xgd}, p, 'linear','none');  % 'linear' instead of 'cubic'
end
%G = griddedInterpolant({b, a, xgd}, p, 'cubic','none');  % original
y = G({beta,alpha,x});
...
</pre>
<p>These cases illustrate two important speedup technique categories: caching data in order to reduce the <i>number of times</i> that a certain code hotspot is being run, and modifying the parameters/inputs in order to reduce the <i>individual run-time</i> of the hotspot code. Variations of these techniques form the essence of effective speedup and can often be achieved by just reflecting on the problem and asking yourself two questions:</p>
<ol>
<li><i>can I reduce the number of times that this code is being run?</i> and</li>
<li><i>can I reduce the run-time of this specific code section?</i></li>
</ol>
<p>Additional important speed-up categories include parallelization, vectorization and algorithmic modification. These are sometimes more difficult programmatically and riskier in terms of functional equivalence, but may be required in case the two main techniques above are not feasible. Of course, we can always combine these techniques, we don't need to choose just one or the other.</p>
<h3 id="stablelike">Speeding-up <i>stablelike()</i></h3>
<p>We now turn our attentions to <i>stablelike()</i>. As for the loaded static file, we could simply use the cached <code>s</code> to load the data in order to avoid repeated reloading of the data from disk. But it turns out that this data is actually not used at all inside the function (!) so we just comment-out the old code:</p>
<pre lang="matlab">
%s = load('private/StablePdfTable.mat');
%a = s.a;
%b = s.b;
%xgd = s.xgd;
%p = s.p;
</pre>
<p>Think about this - the builtin Matlab code loads a data file from disk and then does <i>absolutely nothing</i> with it - what a waste!<br />
Another important change is to reduce the run-time of the <b><i>integral</i></b> function, which is called thousands of times within a double loop. We do this by reducing the tolerances specified in the <b><i>integral</i></b> call from 1e-6:</p>
<pre lang="matlab">
F(i,j) = integral(@(x)infoMtxCal(x,params,step,i,j),-Inf,Inf,'AbsTol',1e-6,'RelTol',1e-4); % original
F(i,j) = integral(@(x)infoMtxCal(x,params,step,i,j),-Inf,Inf,'AbsTol',1e-3,'RelTol',1e-3); % new
</pre>
<p>You can see that once again these two cases follow the two techniques that I mentioned above: we reduced the number of times that we load the data file (to 0 in our case), and we improved the run-time of the individual integral calculation by reducing its tolerances.</p>
<h3 id="conclusions">Conclusions</h3>
<p>The final result of applying the techniques above was a 6-fold speedup, reducing the total run-time from 45 minutes down to 7 minutes. I could probably have improved the run-time even further, but since we reached our target run-time I stopped there. The point after all was to make the code usable, not to reach a world speed record.<br />
In my next article I will present another example of dramatically improving the run-time speed of a built-in Matlab function, this time a very commonly-used function in the Financial Toolbox that I was able to speed-up by a factor of 40.<br />
Matlab releases improve continuously, so hopefully my techniques above (or alternatives) would find their way into the builtin Matlab functions, making them faster than today, out-of-the-box.<br />
Until this happens, we should not lose hope when faced with a slow Matlab function, even if it is a built-in/internal one, as I hope to have clearly illustrated today, and will also show in my next article. Improving the performance is often easy. In fact, it took me much longer to write this article than it was to improve my client's code...<br />
<a href="/consulting" target="_blank">Let me know</a> if you'd like me to assist with your Matlab project, either developing it from scratch or improving your existing code, or just training you in how to improve your Matlab code's run-time/robustness/usability/appearance. I will be visiting Boston and New York in early June and would be happy to meet you in person to discuss your specific needs.</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1">Speeding-up builtin Matlab functions &#8211; part 1</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-2" rel="bookmark" title="Speeding-up builtin Matlab functions &#8211; part 2">Speeding-up builtin Matlab functions &#8211; part 2 </a> <small>Built-in Matlab functions can often be profiled and optimized for improved run-time performance. This article shows a typical example. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/callback-functions-performance" rel="bookmark" title="Callback functions performance">Callback functions performance </a> <small>Using anonymous functions in Matlab callbacks can be very painful for performance. Today's article explains how this can be avoided. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-mouse-pointer-functions" rel="bookmark" title="Undocumented mouse pointer functions">Undocumented mouse pointer functions </a> <small>Matlab contains several well-documented functions and properties for the mouse pointer. However, some very-useful functions have remained undocumented and unsupported. This post details their usage....</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/speeding-up-builtin-matlab-functions-part-1/feed</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Using SQLite in Matlab</title>
		<link>https://undocumentedmatlab.com/articles/using-sqlite-in-matlab?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-sqlite-in-matlab</link>
					<comments>https://undocumentedmatlab.com/articles/using-sqlite-in-matlab#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Wed, 27 Dec 2017 21:53:54 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Undocumented feature]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[JDBC]]></category>
		<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=7255</guid>

					<description><![CDATA[<p>SQLite databases can be accessed in a variety of different ways in Matlab. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/using-sqlite-in-matlab">Using SQLite in Matlab</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/secure-ssl-connection-between-matlab-and-postgresql" rel="bookmark" title="Secure SSL connection between Matlab and PostgreSQL">Secure SSL connection between Matlab and PostgreSQL </a> <small>It is tricky, but quite possible, to use SSL to connect Matlab to a PostgreSQL database. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-toolstrip-part-5-icons" rel="bookmark" title="Matlab toolstrip – part 5 (icons)">Matlab toolstrip – part 5 (icons) </a> <small>Icons can be specified in various ways for toolstrip controls and the app window itself. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/sending-html-emails-from-matlab" rel="bookmark" title="Sending HTML emails from Matlab">Sending HTML emails from Matlab </a> <small>Matlab's sendmail only sends simple text messages by default; a simple hack can cause it to send HTML-formatted messages. ...</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>MathWorks invests a huge amount of effort in recent years on supporting large distributed databases. The business case for this focus is entirely understandable, but many Matlab users have much simpler needs, which are often served by the light-weight open-source <a href="http://sqlite.org" rel="nofollow" target="_blank">SQLite database</a> (which claims to be the most widely-used database worldwide). Although SQLite is very widely used, and despite the fact that built-in support for SQLite is included in Matlab (for its internal use), MathWorks has chosen not to expose any functionality or wrapper function that would enable end-users to access it. In any case, I recently came across a need to do just that, when a consulting client asked me to create an interactive data-browser for their SQLite database that would integrate with their Matlab program:<br />
<center><img decoding="async" src="https://undocumentedmatlab.com/images/DataBrowser_2.png" alt="SQLite data browser" title="SQLite data browser" width="80%" style="max-width:716px;" /></center><br />
In today&#8217;s post I will discuss several possible mechanisms to integrate SQLite in Matlab code, and you can take your pick among them. Except for the Database Toolbox, all the alternatives are free (open-source) libraries (even the commercial Database Toolbox relies on one of the open-source libraries, by the way).<br />
<span id="more-7255"></span></p>
<h3 id="sqlite4java">sqlite4java</h3>
<p><code>sqlite4java</code> is a Java package by <a href="http://almworks.com" rel="nofollow" target="_blank">ALM Works</a> that is bundled with Matlab for the past several years (in the <i>%matlabroot%/java/jarext/sqlite4java/</i> folder). This is a lightweight open-source package that provides a minimalist and fast (although not very convenient) interface to SQLite. You can either use the package that comes with your Matlab installation, or download and use the latest version from <a href="https://bitbucket.org/almworks/sqlite4java" rel="nofollow" target="_blank">the project repository</a>, where you can also find documentation.<br />
Mark Mikofski <a href="http://poquitopicante.blogspot.co.il/2015/03/sqlite-in-matlab.html" rel="nofollow" target="_blank">exposed</a> this hidden nugget back in 2015, and you are welcome to view his post for additional details. Here&#8217;s a sample usage:</p>
<pre lang="matlab">
% Open the DB data file
db = com.almworks.sqlite4java.SQLiteConnection(java.io.File('C:\Yair\Data\IGdb 2017-11-13.sqlite'));
db.open;
% Prepare an SQL query statement
stmt = db.prepare(['select * from data_table where ' conditionStr]);
% Step through the result set rows
row = 1;
while stmt.step
   numericValues(row) = stmt.columnInt(0);    % column #0
   stringValues{row}  = stmt.columnString(1); % column #1
end
% Cleanup
stmt.dispose
db.dispose
</pre>
<p>Note that since <code>sqlite4java</code> uses a proprietary interface (similar, but not identical, to JDBC), it can take a bit of time to get used to it. I am generally a big fan of preferring built-in components over externally-installed ones, but in this particular case I prefer other alternatives.</p>
<h3 id="JDBC">JDBC</h3>
<p><a href="http://www.oracle.com/technetwork/java/javase/jdbc/index.html" rel="nofollow" target="_blank">JDBC</a> (Java Database Connectivity) is the industry standard for connectivity to databases. Practically all databases nowadays have at least one JDBC connector, and many DBs have multiple JDBC drivers created by different groups. As long as they all adhere to the JDBC interface standard, these drivers are all equivalent and you can choose between them based on availability, cost, support, license, performance and other similar factors. SQLite is no exception to this rule, and has several JDBC driver implementations, including xerial&#8217;s <a href="https://bitbucket.org/xerial/sqlite-jdbc" rel="nofollow" target="_blank"><code>sqlite-jdbc</code></a> (also <a href="http://poquitopicante.blogspot.co.il/2015/03/sqlite-in-matlab.html" rel="nofollow" target="_blank">discussed by Mark Mikofski</a>) and <a href="https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sqlitebot/sqlitejdbc-v056.jar" rel="nofollow" target="_blank"><code>sqlitejdbc</code></a>. If you ask me,<br />
 <code>sqlite-jdbc</code> is better as it is being maintained with new versions released periodically.<br />
The example above would look something like this with <code>sqlite-jdbc</code>:</p>
<pre lang="matlab">
% Add the downloaded JAR library file to the dynamic Java classpath
javaaddpath('C:\path\to\sqlite\sqlite-jdbc-3.21.0.jar')
% Open the DB file
jdbc = org.sqlite.JDBC;
props = java.util.Properties;
conn = jdbc.createConnection('jdbc:sqlite:C:\Yair\Data\IGdb 2017-11-13.sqlite',props);  % org.sqlite.SQLiteConnection object
% Prepare and run an SQL query statement
sqlStr = ['select * from data_table where ' conditionStr];
stmt = conn.createStatement;     % org.sqlite.jdbc4.JDBC4Statement object
rs = stmt.executeQuery(sqlStr);  % org.sqlite.jdbc4.JDBC4ResultSet object
% Step through the result set rows
rows = 1;
while rs.next
   numericValues(row) = rs.getLong('ID');
   stringValues{row}  = rs.getString('Name');
end
% Cleanup
rs.close
stmt.close
conn.close
</pre>
<h3 id="toolbox">Database toolbox</h3>
<p>In addition to all the above, MathWorks sells the Database Toolbox which has an <a href="https://www.mathworks.com/help/database/ug/working-with-the-matlab-interface-to-sqlite.html" rel="nofollow" target="_blank">integral SQLite connector</a>, in two flavors &#8211; native and JDBC (the JDBC connector is simply <code>sqlite-jdbc</code> that I mentioned above, see a <a href="https://gist.github.com/cbcunc/e2bc3ef170544e4bf0f0" rel="nofollow" target="_blank">short discussion here</a>).<br />
I assume that the availability of this feature in the DB toolbox is the reason why MathWorks has never created a documented wrapper function for the bundled <code>sqlite4java</code>. I could certainly understand this from a business perspective. Still, with so many free alternatives available as discussed in this post, I see not reason to purchase the toolbox merely for its SQLite connector. Then again, if you need to connect to several different database types, not just SQLite, then getting the toolbox might make sense.</p>
<h3 id="mksqlite">mksqlite</h3>
<p>My personal favorite is actually none of these Java-based connectors (surprise, surprise), but rather the open-source <a href="http://mksqlite.sourceforge.net" rel="nofollow" target="_blank"><code>mksqlite</code> connector</a> by <a href="http://www.kortmann.de" rel="nofollow" target="_blank">Martin Kortmann</a> and <a href="https://github.com/AndreasMartin72" rel="nofollow" target="_blank">Andreas Martin</a>. This is a native (Mex-file) connector that acts as a direct Matlab function. The syntax is pretty straight-forward and supports SQL queries. IMHO, its usage is a much simpler than with any of the other alternatives:</p>
<pre lang="matlab">
% Open the DB file
mksqlite('open', 'C:\Yair\Data\IGdb 2017-11-13.sqlite');
% Query the database
results = mksqlite(['select * from data_table where ' conditionStr]);
numericValues = [results.ID];
stringValues  = {results.Name};
% Cleanup
mksqlite('close');
</pre>
<p>Can it be any simpler than this!?<br />
However, the main benefit of <code>mksqlite</code> over the other connectors is not its simplicity but the connector&#8217;s speed. This speed is due to the fact that the query is vectorized and we do not need to loop over all the separate data rows and fields. With the other connectors, it is actually not the loop that takes so long in Matlab, but rather the overheads and inefficiencies of numerous library calls to fetch one single value at a time from the result-set &#8211; this is avoided in <code>mksqlite</code> where there is only a single call. This results in lightning speed: A couple of years ago I consulted to a client who used a JDBC connector to an SQLite database; by switching from a JDBC connector to <code>mksqlite</code>, I reduced the execution time from 7 secs to 70 msecs &#8211; a 100x speedup! In that specific case, this made the difference between an unusable program and a highly interactive/responsive one.</p>
<h3 id="alternatives">Other alternatives</h3>
<p>In addition to all the above, we can also use a <a href="http://www.codingtricks.biz/working-with-sqlite-database-in-matlab/" rel="nofollow" target="_blank">.NET-based connector</a> or a <a href="https://www.pythoncentral.io/introduction-to-sqlite-in-python/" rel="nofollow" target="_blank">Python one</a> &#8211; I leave these as an exercise for the reader&#8230;<br />
Have I forgotten some important alternative? Or perhaps you have have some related tip you&#8217;d like to share? If so, then please leave a comment below.<br />
Happy New Year everybody!</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/using-sqlite-in-matlab">Using SQLite in Matlab</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/secure-ssl-connection-between-matlab-and-postgresql" rel="bookmark" title="Secure SSL connection between Matlab and PostgreSQL">Secure SSL connection between Matlab and PostgreSQL </a> <small>It is tricky, but quite possible, to use SSL to connect Matlab to a PostgreSQL database. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/speeding-up-matlab-jdbc-sql-queries" rel="bookmark" title="Speeding up Matlab-JDBC SQL queries">Speeding up Matlab-JDBC SQL queries </a> <small>Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-toolstrip-part-5-icons" rel="bookmark" title="Matlab toolstrip – part 5 (icons)">Matlab toolstrip – part 5 (icons) </a> <small>Icons can be specified in various ways for toolstrip controls and the app window itself. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/sending-html-emails-from-matlab" rel="bookmark" title="Sending HTML emails from Matlab">Sending HTML emails from Matlab </a> <small>Matlab's sendmail only sends simple text messages by default; a simple hack can cause it to send HTML-formatted messages. ...</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/using-sqlite-in-matlab/feed</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Tips for accelerating Matlab performance</title>
		<link>https://undocumentedmatlab.com/articles/tips-for-accelerating-matlab-performance?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tips-for-accelerating-matlab-performance</link>
					<comments>https://undocumentedmatlab.com/articles/tips-for-accelerating-matlab-performance#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Thu, 05 Oct 2017 18:25:06 +0000</pubDate>
				<category><![CDATA[Handle graphics]]></category>
		<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Mathworks.com]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pure Matlab]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=7099</guid>

					<description><![CDATA[<p>My article on "Tips for Accelerating MATLAB Performance" was recently featured in the September 2017 Matlab newsletter digest. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/tips-for-accelerating-matlab-performance">Tips for accelerating Matlab performance</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/some-performance-tuning-tips" rel="bookmark" title="Some Matlab performance-tuning tips">Some Matlab performance-tuning tips </a> <small>Matlab can be made to run much faster using some simple optimization techniques. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/new-book-accelerating-matlab-performance" rel="bookmark" title="New book: Accelerating MATLAB Performance">New book: Accelerating MATLAB Performance </a> <small>Accelerating MATLAB Performance (ISBN 9781482211290) is a book dedicated to improving Matlab performance (speed). ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/a-few-parfor-tips" rel="bookmark" title="A few parfor tips">A few parfor tips </a> <small>The parfor (parallel for) loops can be made faster using a few simple tips. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-java-memory-leaks-performance" rel="bookmark" title="Matlab-Java memory leaks, performance">Matlab-Java memory leaks, performance </a> <small>Internal fields of Java objects may leak memory - this article explains how to avoid this without sacrificing performance. ...</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>I&#8217;m proud to report that MathWorks has recently posted my article &#8220;<a href="https://www.mathworks.com/company/newsletters/articles/tips-for-accelerating-matlab-performance.html" rel="nofollow" target="_blank"><i>Tips for Accelerating MATLAB Performance</i></a>&#8221; in their latest newsletter digest (September 2017). This article is an updated and expanded version of <a href="/articles/some-performance-tuning-tips" target="_blank">my post</a> about consulting work that I did for the <a href="http://summit.fas.harvard.edu" rel="nofollow" target="_blank">Crustal Dynamics Research Group</a> at Harvard University, where I helped speed-up a complex Matlab-based GUI by a factor of 50-500 (depending on the specific feature). You can read the full <a href="/articles/some-performance-tuning-tips" target="_blank">detailed technical article</a> here.<br />
<center><figure style="width: 600px" class="wp-caption aligncenter"><a target="_blank" href="/images/ResultManagerGUI.gif"><img loading="lazy" decoding="async" alt="Crustal dynamics visualization GUI" src="https://undocumentedmatlab.com/images/ResultManagerGUI_600x401.gif" title="Crustal dynamics visualization GUI" width="600" height="401" /></a><figcaption class="wp-caption-text">Crustal dynamics visualization GUI</figcaption></figure></center><span id="more-7099"></span><br />
Featuring an article on the official newsletter by a non-MathWorker is rare. Doing this with someone like myself who has a reputation for undocumented aspects, and a consultancy business that potentially competes with theirs, is certainly not obvious. I take this to be a sign that despite the possible drawbacks of publishing my article, MathWorks felt that it provided enough value to the Matlab user community to merit the risk. I applaud MathWorks for this, and thank them for the opportunity of being featured in their official newsletter and conferences. I do not take it for granted in the least.<br />
The newsletter article provides multiple ideas of improving the run-time performance for file I/O and graphics. Many additional techniques for improving Matlab&#8217;s performance can be found under the <a href="/articles/tag/performance" target="_blank">Performance tag</a> in this blog, as well as in my book &#8220;<a href="/books/matlab-performance" target="_blank"><b>Accelerating MATLAB Performance</b></a>&#8221; (CRC Press, 2014, ISBN 978-1482211290).<br />
<!--
Next week I will present live online webinars about various ways to improve Matlab's run-time performance:


<ul>
	

<li>Oct 9, 2017 (Mon) - <a target="_blank" href="/courses/Matlab_Performance_Tuning_1_Webinar.pdf">Matlab performance tuning part 1</a> - $295 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&currency_code=USD&business=octahedron.ltd@gmail.com&quantity=1&amount=295&item_name=Matlab+performance+1+webinar" rel="nofollow" target="_blank">buy</a>)</li>


	

<li>Oct 10, 2017 (Tue) - <a target="_blank" href="/courses/Matlab_Performance_Tuning_2_Webinar.pdf">Matlab performance tuning part 2</a> - $295 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&currency_code=USD&business=octahedron.ltd@gmail.com&quantity=1&amount=295&item_name=Matlab+performance+2+webinar" rel="nofollow" target="_blank">buy</a>)
 &nbsp;&nbsp;&nbsp; ==> or buy both Matlab performance tuning webinars for only $495 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&currency_code=USD&business=octahedron.ltd@gmail.com&quantity=1&amount=495&item_name=Matlab+performance+webinars" rel="nofollow" target="_blank">buy</a>)</li>


</ul>


These live webinars will be 3.5 hours long, starting at 10am EDT (7am PDT, 3pm UK, 4pm CET, 7:30pm IST, <a href="https://www.google.com/search?q=9am+edt+to+my+time" rel="nofollow" target="_blank">time in your local timezone</a>), with a short break in the middle. The presentations content will be based on onsite training courses that I presented at multiple client locations (<a href="/training#onsite" target="_blank">details</a>). A recording of the webinars will be available for anyone who cannot join the live events.
--><br />
I am offering a couple of webinars about various ways to improve Matlab&#8217;s run-time performance:</p>
<ul>
<li><a target="_blank" href="/courses/Matlab_Performance_Tuning_1_Webinar.pdf">Matlab performance tuning part 1</a> (3:39 hours, <a target="_blank" href="/courses/Matlab_Performance_Tuning_1_Webinar.pdf">syllabus</a>) &#8211; $195 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&#038;currency_code=USD&#038;business=octahedron.ltd@gmail.com&#038;quantity=1&#038;amount=195&#038;item_name=Matlab+performance+1+webinar" rel="nofollow" target="_blank">buy</a>)</li>
<li><a target="_blank" href="/courses/Matlab_Performance_Tuning_2_Webinar.pdf">Matlab performance tuning part 2</a> (3:43 hours, <a target="_blank" href="/courses/Matlab_Performance_Tuning_2_Webinar.pdf">syllabus</a>) &#8211; $195 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&#038;currency_code=USD&#038;business=octahedron.ltd@gmail.com&#038;quantity=1&#038;amount=195&#038;item_name=Matlab+performance+2+webinar" rel="nofollow" target="_blank">buy</a>)<br />
 &nbsp;&nbsp;&nbsp; ==> or buy both Matlab performance tuning webinars for only $345 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&#038;currency_code=USD&#038;business=octahedron.ltd@gmail.com&#038;quantity=1&#038;amount=345&#038;item_name=Matlab+performance+webinars" rel="nofollow" target="_blank">buy</a>)</li>
</ul>
<p>Both the webinar videos and their corresponding slide-decks are available for download. The webinars content is based on onsite training courses that I presented at multiple client locations (<a href="/training#onsite" target="_blank">details</a>).<br />
<a href="mailto: altmany @gmail.com?subject=Matlab webinars&#038;body=Hi Yair, &#038;cc=;&#038;bcc=" rel="nofollow" target="_blank" onclick="var n='altmany'; var d='gmail.com'; window.open('mailto:'+n+'@'+d+'?subject=Matlab webinars&#038;body=Hi Yair, '); return false;"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/email-icon.png" width="32" height="22" alt="" style="vertical-align:middle;border:0"/>&nbsp;Email me</a> if you would like additional information on the webinars or my consulting, or to inquire regarding an onsite training course.</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/tips-for-accelerating-matlab-performance">Tips for accelerating Matlab performance</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/some-performance-tuning-tips" rel="bookmark" title="Some Matlab performance-tuning tips">Some Matlab performance-tuning tips </a> <small>Matlab can be made to run much faster using some simple optimization techniques. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/new-book-accelerating-matlab-performance" rel="bookmark" title="New book: Accelerating MATLAB Performance">New book: Accelerating MATLAB Performance </a> <small>Accelerating MATLAB Performance (ISBN 9781482211290) is a book dedicated to improving Matlab performance (speed). ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/a-few-parfor-tips" rel="bookmark" title="A few parfor tips">A few parfor tips </a> <small>The parfor (parallel for) loops can be made faster using a few simple tips. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-java-memory-leaks-performance" rel="bookmark" title="Matlab-Java memory leaks, performance">Matlab-Java memory leaks, performance </a> <small>Internal fields of Java objects may leak memory - this article explains how to avoid this without sacrificing performance. ...</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/tips-for-accelerating-matlab-performance/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Faster csvwrite/dlmwrite</title>
		<link>https://undocumentedmatlab.com/articles/faster-csvwrite-dlmwrite?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=faster-csvwrite-dlmwrite</link>
					<comments>https://undocumentedmatlab.com/articles/faster-csvwrite-dlmwrite#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Tue, 03 Oct 2017 15:00:05 +0000</pubDate>
				<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Mex]]></category>
		<category><![CDATA[Undocumented feature]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Pure Matlab]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=7080</guid>

					<description><![CDATA[<p>The speed of the builtin csvwrite, dlmwrite functions can be improved dramatically. </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/faster-csvwrite-dlmwrite">Faster csvwrite/dlmwrite</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/faster-findjobj" rel="bookmark" title="Faster findjobj">Faster findjobj </a> <small>the ubiquitous findjobj utility has been significantly improved for speed for the most common use case. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/mex-ctrl-c-interrupt" rel="bookmark" title="MEX ctrl-c interrupt">MEX ctrl-c interrupt </a> <small>An undocumented MEX function can help interrupt running MEX functions. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matrix-processing-performance" rel="bookmark" title="Matrix processing performance">Matrix processing performance </a> <small>Matrix operations performance is affected by internal subscriptions in a counter-intuitive way....</small></li>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part3" rel="bookmark" title="Explicit multi-threading in Matlab part 3">Explicit multi-threading in Matlab part 3 </a> <small>Matlab performance can be improved by employing POSIX threads in C/C++ code. ...</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>Matlab&#8217;s builtin functions for exporting (saving) data to output files are quite sub-optimal (as in <i>slowwwwww&#8230;</i>). I wrote a few posts about this in the past (how to improve <a href="/articles/improving-fwrite-performance" target="_blank"><i><b>fwrite</b></i> performance</a>, and <a href="/articles/improving-save-performance" target="_blank"><i><b>save</b></i> performance</a>). Today I extend the series by showing how we can improve the performance of delimited text output, for example comma-separated (CSV) or tab-separated (TSV/TXT) files.<br />
The basic problem is that Matlab&#8217;s <i><b>dlmwrite</b></i> function, which can either be used directly, or via the <i><b>csvwrite</b></i> function which calls it internally, is extremely inefficient: It processes each input data value separately, in a non-vectorized loop. In the general (completely non-vectorized) case, each data value is separately converted into a string, and is separately sent to disk (using <i><b>fprintf</b></i>). In the specific case of real data values with simple delimiters and formatting, row values are vectorized, but in any case the rows are processed in a non-vectorized loop: A newline character is separately exported at the end of each row, using a separate <i><b>fprintf</b></i> call, and this has the effect of flushing the I/O to disk each and every row separately, which is of course disastrous for performance. The output file is indeed originally opened in buffered mode (as I explained in my <a href="/articles/improving-fwrite-performance" target="_blank"><i><b>fprintf</b></i> performance</a> post), but this only helps for outputs done within the row &#8211; the newline output at the end of each row forces an I/O flush regardless of how the file was opened. In general, when you read the short source-code of <i>dlmwrite.m</i> you&#8217;ll get the distinct feeling that it was written for correctness and maintainability, and some focus on performance (e.g., the vectorization edge-case). But much more could be done for performance it would seem.<br />
This is where Alex Nazarovsky comes to the rescue.<br />
<span id="more-7080"></span><br />
Alex was so bothered by the slow performance of <i><b>csvwrite</b></i> and <i><b>dlmwrite</b></i> that he created a C++ (MEX) version that runs about enormously faster (30 times faster on my system). He <a href="http://nazarovsky.ru/2014/08/22/fast-csv-values-export-to-file-mex-based-dlmwrite-replacement-for-matlab" rel="nofollow" target="_blank">explains the idea</a> in his blog, and posted it as an open-source utility (<a href="https://github.com/nazarovsky/mex-writematrix" rel="nofollow" target="_blank">mex-writematrix</a>) on GitHub.<br />
Usage of Alex&#8217;s utility is very easy:</p>
<pre lang="matlab">mex_WriteMatrix(filename, dataMatrix, textFormat, delimiter, writeMode);</pre>
<p>where the input arguments are:</p>
<ul>
<li>filename &#8211; full path name for file to export</li>
<li>dataMatrix &#8211; matrix of numeric values to be exported</li>
<li>textFormat &#8211; format of output text (<i><b>sprintf</b></i> format), e.g. <code>'%10.6f'</code></li>
<li>delimiter &#8211; delimiter, for example <code>','</code> or <code>';'</code> or <code>char(9)</code> (=tab)</li>
<li>writeMode &#8211; <code>'w+'</code> for rewriting file; <code>'a+'</code> for appending (note the lowercase: uppercase will crash Matlab!)</li>
</ul>
<p>Here is a sample run on my system, writing a simple CSV file containing 1K-by-1K data values (1M elements, ~12MB text files):</p>
<pre lang="matlab">
>> data = rand(1000, 1000);  % 1M data values, 8MB in memory, ~12MB on disk
>> tic, dlmwrite('temp1.csv', data, 'delimiter',',', 'precision','%10.10f'); toc
Elapsed time is 28.724937 seconds.
>> tic, mex_WriteMatrix('temp2.csv', data, '%10.10f', ',', 'w+'); toc   % 30 times faster!
Elapsed time is 0.957256 seconds.
</pre>
<p>Alex&#8217;s <i><b>mex_WriteMatrix</b></i> function is faster even in the edge case of simple formatting where <i><b>dlmwrite</b></i> uses vectorized mode (in that case, the file is exported in ~1.2 secs by <i><b>dlmwrite</b></i> and ~0.9 secs by <i><b>mex_WriteMatrix</b></i>, on my system).</p>
<h3 id="ctrl-c">Trapping Ctrl-C interrupts</h3>
<p>Alex&#8217;s <i><b>mex_WriteMatrix</b></i> code includes another undocumented trick that could help anyone else who uses a long-running MEX function, namely the ability to stop the MEX execution using Ctrl-C. Using Ctrl-C is normally ignored in MEX code, but <a href="http://www.caam.rice.edu/~wy1/links/mex_ctrl_c_trick" rel="nofollow" target="_blank">Wotao Yin showed</a> how we can use the undocumented <i>utIsInterruptPending()</i> MEX function to monitor for user interrupts using Ctrl-C. For easy reference, here is a copy of Wotao Yin&#8217;s usage example (read <a href="http://www.caam.rice.edu/~wy1/links/mex_ctrl_c_trick" rel="nofollow" target="_blank">his webpage</a> for additional details):</p>
<pre lang="cpp">
/* A demo of Ctrl-C detection in mex-file by Wotao Yin. Jan 29, 2010. */
#include "mex.h"
#if defined (_WIN32)
    #include <windows.h>
#elif defined (__linux__)
    #include <unistd.h>
#endif
#ifdef __cplusplus
    extern "C" bool utIsInterruptPending();
#else
    extern bool utIsInterruptPending();
#endif
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    int count = 0;
    while(1) {
        #if defined(_WIN32)
            Sleep(1000);        /* Sleep one second */
        #elif defined(__linux__)
            usleep(1000*1000);  /* Sleep one second */
        #endif
        mexPrintf("Count = %d\n", count++);  /* print count and increase it by 1 */
        mexEvalString("drawnow;");           /* flush screen output */
        if (utIsInterruptPending()) {        /* check for a Ctrl-C event */
            mexPrintf("Ctrl-C Detected. END\n\n");
            return;
        }
        if (count == 10) {
            mexPrintf("Count Reached 10. END\n\n");
            return;
        }
    }
}
</pre>
<h3 id="webinars">Matlab performance webinars</h3>
<p><!--
Next week I will present live online webinars about numerous other ways to improve Matlab's run-time performance:


<ul>
	

<li>Oct 9, 2017 (Mon) - <a target="_blank" href="/courses/Matlab_Performance_Tuning_1_Webinar.pdf">Matlab performance tuning part 1</a> - $295 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&currency_code=USD&business=octahedron.ltd@gmail.com&quantity=1&amount=295&item_name=Matlab+performance+1+webinar" rel="nofollow" target="_blank">buy</a>)</li>


	

<li>Oct 10, 2017 (Tue) - <a target="_blank" href="/courses/Matlab_Performance_Tuning_2_Webinar.pdf">Matlab performance tuning part 2</a> - $295 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&currency_code=USD&business=octahedron.ltd@gmail.com&quantity=1&amount=295&item_name=Matlab+performance+2+webinar" rel="nofollow" target="_blank">buy</a>)
 &nbsp;&nbsp;&nbsp; ==> or buy both Matlab performance tuning webinars for only $495 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&currency_code=USD&business=octahedron.ltd@gmail.com&quantity=1&amount=495&item_name=Matlab+performance+webinars" rel="nofollow" target="_blank">buy</a>)</li>


</ul>


These live webinars will be 3.5 hours long, starting at 10am EDT (7am PDT, 3pm UK, 4pm CET, 7:30pm IST, <a href="https://www.google.com/search?q=9am+edt+to+my+time" rel="nofollow" target="_blank">time in your local timezone</a>), with a short break in the middle. The presentations content will be based on onsite training courses that I presented at multiple client locations (<a href="/training#onsite" target="_blank">details</a>). A recording of the webinars will be available for anyone who cannot join the live events.
--><br />
I am offering a couple of webinars about various ways to improve Matlab&#8217;s run-time performance:</p>
<ul>
<li><a target="_blank" href="/courses/Matlab_Performance_Tuning_1_Webinar.pdf">Matlab performance tuning part 1</a> (3:39 hours, <a target="_blank" href="/courses/Matlab_Performance_Tuning_1_Webinar.pdf">syllabus</a>) &#8211; $195 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&#038;currency_code=USD&#038;business=octahedron.ltd@gmail.com&#038;quantity=1&#038;amount=195&#038;item_name=Matlab+performance+1+webinar" rel="nofollow" target="_blank">buy</a>)</li>
<li><a target="_blank" href="/courses/Matlab_Performance_Tuning_2_Webinar.pdf">Matlab performance tuning part 2</a> (3:43 hours, <a target="_blank" href="/courses/Matlab_Performance_Tuning_2_Webinar.pdf">syllabus</a>) &#8211; $195 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&#038;currency_code=USD&#038;business=octahedron.ltd@gmail.com&#038;quantity=1&#038;amount=195&#038;item_name=Matlab+performance+2+webinar" rel="nofollow" target="_blank">buy</a>)<br />
 &nbsp;&nbsp;&nbsp; ==> or buy both Matlab performance tuning webinars for only $345 (<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&#038;currency_code=USD&#038;business=octahedron.ltd@gmail.com&#038;quantity=1&#038;amount=345&#038;item_name=Matlab+performance+webinars" rel="nofollow" target="_blank">buy</a>)</li>
</ul>
<p>Both the webinar videos and their corresponding slide-decks are available for download. The webinars content is based on onsite training courses that I presented at multiple client locations (<a href="/training#onsite" target="_blank">details</a>).<br />
Additional Matlab performance tips can be found under the <a href="/articles/tag/performance" target="_blank">Performance tag</a> in this blog, as well as in my book &#8220;<a href="/books/matlab-performance" target="_blank"><b>Accelerating MATLAB Performance</b></a>&#8220;.<br />
<a href="mailto: altmany @gmail.com?subject=Matlab webinars&#038;body=Hi Yair, &#038;cc=;&#038;bcc=" rel="nofollow" target="_blank" onclick="var n='altmany'; var d='gmail.com'; window.open('mailto:'+n+'@'+d+'?subject=Matlab webinars&#038;body=Hi Yair, '); return false;"><img loading="lazy" decoding="async" src="https://undocumentedmatlab.com/images/email-icon.png" width="32" height="22" alt="" style="vertical-align:middle;border:0"/>&nbsp;Email me</a> if you would like additional information on the webinars, or an onsite training course, or about my consulting.</p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/faster-csvwrite-dlmwrite">Faster csvwrite/dlmwrite</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/faster-findjobj" rel="bookmark" title="Faster findjobj">Faster findjobj </a> <small>the ubiquitous findjobj utility has been significantly improved for speed for the most common use case. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/mex-ctrl-c-interrupt" rel="bookmark" title="MEX ctrl-c interrupt">MEX ctrl-c interrupt </a> <small>An undocumented MEX function can help interrupt running MEX functions. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matrix-processing-performance" rel="bookmark" title="Matrix processing performance">Matrix processing performance </a> <small>Matrix operations performance is affected by internal subscriptions in a counter-intuitive way....</small></li>
<li><a href="https://undocumentedmatlab.com/articles/explicit-multi-threading-in-matlab-part3" rel="bookmark" title="Explicit multi-threading in Matlab part 3">Explicit multi-threading in Matlab part 3 </a> <small>Matlab performance can be improved by employing POSIX threads in C/C++ code. ...</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/faster-csvwrite-dlmwrite/feed</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Parsing XML strings</title>
		<link>https://undocumentedmatlab.com/articles/parsing-xml-strings?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=parsing-xml-strings</link>
					<comments>https://undocumentedmatlab.com/articles/parsing-xml-strings#comments</comments>
		
		<dc:creator><![CDATA[Yair Altman]]></dc:creator>
		<pubDate>Wed, 01 Feb 2017 09:52:45 +0000</pubDate>
				<category><![CDATA[Low risk of breaking in future versions]]></category>
		<category><![CDATA[Semi-documented feature]]></category>
		<category><![CDATA[Stock Matlab function]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[XML]]></category>
		<guid isPermaLink="false">http://undocumentedmatlab.com/?p=6838</guid>

					<description><![CDATA[<p>Matlab's xmlread function cannot process XML data directly, but this can easily be overcome.  </p>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/parsing-xml-strings">Parsing XML strings</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/parsing-mlint-code-analyzer-output" rel="bookmark" title="Parsing mlint (Code Analyzer) output">Parsing mlint (Code Analyzer) output </a> <small>The Matlab Code Analyzer (mlint) has a lot of undocumented functionality just waiting to be used. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/file-deletion-memory-leaks-performance" rel="bookmark" title="File deletion memory leaks, performance">File deletion memory leaks, performance </a> <small>Matlab's delete function leaks memory and is also slower than the equivalent Java function. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-compiler-bug-and-workaround" rel="bookmark" title="Matlab compiler bug and workaround">Matlab compiler bug and workaround </a> <small>Both the Matlab compiler and the publish function have errors when parsing block-comments in Matlab m-code. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-xml-functionality" rel="bookmark" title="Undocumented XML functionality">Undocumented XML functionality </a> <small>Matlab's built-in XML-processing functions have several undocumented features that can be used by Java-savvy users...</small></li>
</ol>
</div>
]]></description>
										<content:encoded><![CDATA[<p>I have recently consulted in a project where data was provided in XML strings and needed to be parsed in Matlab memory in an efficient manner (in other words, as quickly as possible). Now granted, XML is rather inefficient in storing data (JSON would be much better for this, for example). But I had to work with the given situation, and that required processing the XML.<br />
I basically had two main alternatives:</p>
<ul>
<li>I could either create a dedicated string-parsing function that searches for a particular pattern within the XML string, or</li>
<li>I could use a standard XML-parsing library to create the XML model and then parse its nodes</li>
</ul>
<p>The first alternative is quite error-prone, since it relies on the exact format of the data in the XML. Since the same data can be represented in multiple equivalent XML ways, making the string-parsing function robust as well as efficient would be challenging. I was <del>lazy</del> expedient, so I chose the second alternative.<br />
Unfortunately, Matlab&#8217;s <i><b>xmlread</b></i> function only accepts input filenames (of *.xml files), it cannot directly parse XML strings. Yummy!<br />
The obvious and simple solution is to simply write the XML string into a temporary *.xml file, read it with <i><b>xmlread</b></i>, and then delete the temp file:</p>
<pre lang="matlab">
% Store the XML data in a temp *.xml file
filename = [tempname '.xml'];
fid = fopen(filename,'Wt');
fwrite(fid,xmlString);
fclose(fid);
% Read the file into an XML model object
xmlTreeObject = xmlread(filename);
% Delete the temp file
delete(filename);
% Parse the XML model object
...
</pre>
<p>This works well and we could move on with our short lives. But cases such as this, where a built-in function seems to have a silly limitation, really fire up the investigative reporter in me. I decided to drill into <i><b>xmlread</b></i> to discover why it couldn&#8217;t parse XML strings directly in memory, without requiring costly file I/O. It turns out that <i><b>xmlread</b></i> accepts not just file <i>names</i> as input, but also Java object references (specifically, <a href="http://docs.oracle.com/javase/7/docs/api/java/io/File.html" rel="nofollow" target="_blank"><code>java.io.File</code></a>, <a href="http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html" rel="nofollow" target="_blank"><code>java.io.InputStream</code></a> or <a href="http://docs.oracle.com/javase/7/docs/api/org/xml/sax/InputSource.html" rel="nofollow" target="_blank"><code>org.xml.sax.InputSource</code></a>). In fact, there are quite a few other inputs that we could use, to specify a validation parser etc. &#8211; <a href="/articles/undocumented-xml-functionality" target="_blank">I wrote about this briefly</a> back in 2009 (along with other similar semi-documented input altermatives in <i><b>xmlwrite</b></i> and <i><b>xslt</b></i>).<br />
<span id="more-6838"></span><br />
In our case, we could simply send <i><b>xmlread</b></i> as input a <code><a href="http://docs.oracle.com/javase/7/docs/api/java/io/StringBufferInputStream.html" rel="nofollow" target="_blank">java.io.StringBufferInputStream</a>(xmlString)</code> object (which is an instance of <code>java.io.InputStream</code>) or <code>org.xml.sax.InputSource(java.io.StringReader(xmlString))</code>:</p>
<pre lang="matlab">
% Read the xml string directly into an XML model object
inputObject = java.io.StringBufferInputStream(xmlString);                % alternative #1
inputObject = org.xml.sax.InputSource(java.io.StringReader(xmlString));  % alternative #2
xmlTreeObject = xmlread(inputObject);
% Parse the XML model object
...
</pre>
<p>If we don&#8217;t want to depend on undocumented functionality (which might break in some future release, although it has remained unchanged for at least the past decade), and in order to improve performance even further by passing <i><b>xmlread</b></i>&#8216;s internal validity checks and processing, we can use <i><b>xmlread</b></i>&#8216;s core functionality to parse our XML string directly. We can add a fallback to the standard (fully-documented) functionality, just in case something goes wrong (which is good practice whenever using any undocumented functionality):</p>
<pre lang="matlab">
try
    % The following avoids the need for file I/O:
    inputObject = java.io.StringBufferInputStream(xmlString);  % or: org.xml.sax.InputSource(java.io.StringReader(xmlString))
    try
        % Parse the input data directly using xmlread's core functionality
        parserFactory = javaMethod('newInstance','javax.xml.parsers.DocumentBuilderFactory');
        p = javaMethod('newDocumentBuilder',parserFactory);
        xmlTreeObject = p.parse(inputObject);
    catch
        % Use xmlread's semi-documented inputObject input feature
        xmlTreeObject = xmlread(inputObject);
    end
catch
    % Fallback to standard xmlread usage, using a temporary XML file:
    % Store the XML data in a temp *.xml file
    filename = [tempname '.xml'];
    fid = fopen(filename,'Wt');
    fwrite(fid,xmlString);
    fclose(fid);
    % Read the file into an XML model object
    xmlTreeObject = xmlread(filename);
    % Delete the temp file
    delete(filename);
end
% Parse the XML model object
...
</pre>
<p>The post <a rel="nofollow" href="https://undocumentedmatlab.com/articles/parsing-xml-strings">Parsing XML strings</a> appeared first on <a rel="nofollow" href="https://undocumentedmatlab.com">Undocumented Matlab</a>.</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="https://undocumentedmatlab.com/articles/parsing-mlint-code-analyzer-output" rel="bookmark" title="Parsing mlint (Code Analyzer) output">Parsing mlint (Code Analyzer) output </a> <small>The Matlab Code Analyzer (mlint) has a lot of undocumented functionality just waiting to be used. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/file-deletion-memory-leaks-performance" rel="bookmark" title="File deletion memory leaks, performance">File deletion memory leaks, performance </a> <small>Matlab's delete function leaks memory and is also slower than the equivalent Java function. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/matlab-compiler-bug-and-workaround" rel="bookmark" title="Matlab compiler bug and workaround">Matlab compiler bug and workaround </a> <small>Both the Matlab compiler and the publish function have errors when parsing block-comments in Matlab m-code. ...</small></li>
<li><a href="https://undocumentedmatlab.com/articles/undocumented-xml-functionality" rel="bookmark" title="Undocumented XML functionality">Undocumented XML functionality </a> <small>Matlab's built-in XML-processing functions have several undocumented features that can be used by Java-savvy users...</small></li>
</ol>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://undocumentedmatlab.com/articles/parsing-xml-strings/feed</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
	</channel>
</rss>
