<?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>The ILNumerics Blog &#187; plots</title>
	<atom:link href="https://ilnumerics.net/blog/tag/plots/feed/" rel="self" type="application/rss+xml" />
	<link>https://ilnumerics.net/blog</link>
	<description>The Productivity Machine  &#124;  A fresh attempt for scientific computing  &#124;  http://ilnumerics.net</description>
	<lastBuildDate>Thu, 05 Dec 2024 09:09:24 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.41</generator>
	<item>
		<title>ILNumerics for Science &#8211; How did you do the Visualization?</title>
		<link>https://ilnumerics.net/blog/ilnumerics-for-scientists-how-did-you-do-the-visualization/</link>
		<comments>https://ilnumerics.net/blog/ilnumerics-for-scientists-how-did-you-do-the-visualization/#comments</comments>
		<pubDate>Mon, 02 Feb 2015 16:35:03 +0000</pubDate>
		<dc:creator><![CDATA[Jonas]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[ILNumerics]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[3d visualization]]></category>
		<category><![CDATA[plots]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://ilnumerics.net/blog/?p=772</guid>
		<description><![CDATA[<p>In the third part of our series we focus on the visualization of scientific data. You learn how to easily display your data with ILNumerics and the ILPanels. Reactions I got a lot of emails after the last two posts (first, second) of people that liked the post and are interested in learning more. Most &#8230; <a href="https://ilnumerics.net/blog/ilnumerics-for-scientists-how-did-you-do-the-visualization/" class="more-link">Continue reading <span class="screen-reader-text">ILNumerics for Science &#8211; How did you do the Visualization?</span> <span class="meta-nav">&#8594;</span></a></p>
<p>The post <a rel="nofollow" href="https://ilnumerics.net/blog/ilnumerics-for-scientists-how-did-you-do-the-visualization/">ILNumerics for Science &#8211; How did you do the Visualization?</a> appeared first on <a rel="nofollow" href="https://ilnumerics.net/blog">The ILNumerics Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In the third part of our series we focus on the visualization of scientific data. You learn how to easily display your data with ILNumerics and the ILPanels.</p>
<p><span id="more-772"></span></p>
<h3>Reactions</h3>
<p style="text-align: justify;">I got a lot of emails after the last two posts (<a title="ILNumerics for Scientists – An easy start" href="http://ilnumerics.net/blog/ilnumerics-for-scientists-an-easy-start/">first</a>, <a title="ILNumerics for Scientists – Going 3D" href="http://ilnumerics.net/blog/ilnumerics-for-scientists/">second</a>) of people that liked the post and are interested in learning more. Most emails asked me to go into more details about how I did all that. Obviously, not too many people are interested in implementing the particle in a box, so the “what” is not as interesting as the “how”.</p>
<p style="text-align: justify;">In this post I want to focus on the visualization part of the previous two examples and how <a href="http://ilnumerics.net">ILNumerics </a>helped me. As many of our users are scientists and engineers they are typically experts in the computation part but appreciate a little help in the visualization. If you&#8217;re interested in the computation part, please be patient until the next post.</p>
<h3>The Form</h3>
<p style="text-align: justify;">I started by creating a new project in Visual Studio and chose Windows Forms Application. This gives me a vanilla Form1.cs. That’s the basis of all the visualization and helps me – being a scientist and not a coder – a lot, because I couldn’t do all that without the help of Visual Studio in the background.</p>
<p style="text-align: justify;">On the left-hand side in the Toolbox panel I picked TableLayoutPanel under Containers and dragged it into Form1.cs.</p>
<p style="text-align: justify;"><a href="http://ilnumerics.net/blog/wp-content/uploads/2015/02/firstimage.png"><img class="alignnone size-full wp-image-775" src="http://ilnumerics.net/blog/wp-content/uploads/2015/02/firstimage.png" alt="firstimage" width="421" height="379" /></a></p>
<p style="text-align: justify;">I adjusted the table to have three rows and a single column. In the Properties section under Dock I chose Fill so that everything scales when scaling the window later on.</p>
<p style="text-align: justify;"><a href="http://ilnumerics.net/blog/wp-content/uploads/2015/02/secondimage.png"><img class="alignnone size-full wp-image-777" src="http://ilnumerics.net/blog/wp-content/uploads/2015/02/secondimage.png" alt="secondimage" width="404" height="475" /></a></p>
<p style="text-align: justify;">A right click on Table -&gt; Edit Rows and Columns allows you to change the behavior of the three rows. I wanted the first and last row not to scale when changing the window. This is what I chose here.</p>
<p style="text-align: justify;"><a href="http://ilnumerics.net/blog/wp-content/uploads/2015/02/thirdimage.png"><img class="alignnone size-full wp-image-779" src="http://ilnumerics.net/blog/wp-content/uploads/2015/02/thirdimage.png" alt="thirdimage" width="730" height="481" /></a></p>
<p style="text-align: justify;">In the middle row we would like to see two ILNumerics panels. So I dragged another TableLayoutPanel in the middle row and chose two columns and one row. Choosing Dock = Fill for the new table and dragging two ILPanels into the respective columns (again with Dock = Fill) gives us the layout for our final Windows Form.</p>
<p style="text-align: justify;"><a href="http://ilnumerics.net/blog/wp-content/uploads/2015/02/fourthimage.png"><img class="alignnone size-full wp-image-776" src="http://ilnumerics.net/blog/wp-content/uploads/2015/02/fourthimage.png" alt="fourthimage" width="685" height="623" /></a></p>
<p style="text-align: justify;">In the header (the first row) I inserted a FlowLayoutPanel that makes sure that everything in there will be displayed rather neatly. Then I added the labels and the NumericUpDown according to my needs. Please make sure that you go through the properties of every item and choose the values according to your needs. In my case, for instance, the minimum value for the state is 1, since 0 would mean that there is no particle present. Here is the final picture of the form for the 1D particle in a box:</p>
<p><a href="http://ilnumerics.net/blog/wp-content/uploads/2015/02/fifthimage.png"><img class="alignnone size-full wp-image-774" src="http://ilnumerics.net/blog/wp-content/uploads/2015/02/fifthimage.png" alt="fifthimage" width="935" height="660" /></a></p>
<h3>The Wiring</h3>
<p style="text-align: justify;">After having the layout ready the interactivity needs to be implemented. In this case there is only one point of user interaction. The user can choose which eigenvector to display. Double-clicking on the NumericUpDown control opens a new tab with a predefined class and a function handling the event when a user changes the value of the eigenvector.</p>
<p style="text-align: justify;"><a href="http://ilnumerics.net/blog/wp-content/uploads/2015/02/sixthimage.png"><img class="alignnone size-full wp-image-778" src="http://ilnumerics.net/blog/wp-content/uploads/2015/02/sixthimage.png" alt="sixthimage" width="589" height="477" /></a></p>
<p style="text-align: justify;">All that’s needed now is to implement the function numericUpDown1_ValueChanged. This is particularly simple in our case. We just call the Update function (still to be implemented) with the new value for the eigenvector.</p>
<p style="text-align: justify;">In the case of the 2D particle in a box we have, in fact, four events that should trigger the Update function. This is easily done by introducing these lines of code in the public function Form1():</p>
<pre class="brush: csharp; title: ; notranslate">
     numericUpDown1.ValueChanged += Update;
     numericUpDown2.ValueChanged += Update;
     numericUpDown3.ValueChanged += Update;
     textBox1.TextChanged += Update;
</pre>
<h3 style="text-align: left;">The Implementation</h3>
<p style="text-align: justify;">Now, all we need to do is to implement the Update function and the initialization. The initialization makes sure that all the plotting objects are created when starting the program.</p>
<pre class="brush: csharp; title: ; notranslate">
     public Form1()
     {
        InitializeComponent();

        var EVID = 1;
        var MeshSize = 1000;

        InitializePanel1(EVID, MeshSize);
        InitializePanel2(EVID, MeshSize);

        label2.Text = string.Format(&quot;In appropriate units the energy is {0}&quot;, EVID * EVID);
     }

     private void InitializePanel1(int EVID, int MeshSize)
     {
        ILArray&lt;float&gt; XY = ILMath.tosingle(Computing_Module1.CalcWF(EVID, MeshSize));
        var color = Color.Black;
        ilPanel1.Scene =
          new ILScene {
            new ILPlotCube {
              new ILLinePlot (XY, lineColor : color)
            }
          };
     }
</pre>
<p style="text-align: justify;">The call to Computing_Module1.CalcWF will be explained in the next post. The piece of code above initializes the wave function plot and the density plot in their respective panels with the first eigenvector and a mesh size of 1000.</p>
<p>Finally, the Update function is implemented.</p>
<pre class="brush: csharp; title: ; notranslate">
     private void Update(int EVID, int MeshSize = 1000)
     {
       ILArray&lt;float&gt; XY = ILMath.tosingle(Computing_Module1.CalcWF(EVID, MeshSize));
       ilPanel1.Scene.First&lt;ILLinePlot&gt;().Update(XY);
       ilPanel1.Scene.First&lt;ILPlotCube&gt;().Reset();
       ilPanel1.Refresh();

       ILArray&lt;float&gt; XD = ILMath.tosingle(Computing_Module1.CalcDensity(EVID, MeshSize));
       ilPanel2.Scene.First&lt;ILLinePlot&gt;().Update(XD);
       ilPanel2.Scene.First&lt;ILPlotCube&gt;().Reset();
       ilPanel2.Refresh();
       label2.Text = string.Format(&quot;In appropriate units the energy is {0}&quot;, EVID * EVID);
     }
</pre>
<p style="text-align: justify;">Again, the CalcWF and CalcDensity calls will be explained in the next post. The Reset() function rescales the axes and the Refresh() function finally puts the new plot on screen.</p>
<p>The post <a rel="nofollow" href="https://ilnumerics.net/blog/ilnumerics-for-scientists-how-did-you-do-the-visualization/">ILNumerics for Science &#8211; How did you do the Visualization?</a> appeared first on <a rel="nofollow" href="https://ilnumerics.net/blog">The ILNumerics Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://ilnumerics.net/blog/ilnumerics-for-scientists-how-did-you-do-the-visualization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Plotting Fun with ILNumerics and IronPython</title>
		<link>https://ilnumerics.net/blog/plotting-fun-with-ilnumerics-and-ironpython/</link>
		<comments>https://ilnumerics.net/blog/plotting-fun-with-ilnumerics-and-ironpython/#comments</comments>
		<pubDate>Mon, 15 Sep 2014 10:31:45 +0000</pubDate>
		<dc:creator><![CDATA[haymo]]></dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ILNumerics]]></category>
		<category><![CDATA[Usage]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[numerical algorithms]]></category>
		<category><![CDATA[plots]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ilnumerics.net/blog/?p=599</guid>
		<description><![CDATA[<p>Since the early days of IronPython, I keep shifting one bullet point down on my ToDo list: * Evaluate options to use ILNumerics from IronPython Several years ago there has been some attempts from ILNumerics users who successfully utilized ILNumerics from within IronPython. But despite our fascination for these attempts, we were not able to &#8230; <a href="https://ilnumerics.net/blog/plotting-fun-with-ilnumerics-and-ironpython/" class="more-link">Continue reading <span class="screen-reader-text">Plotting Fun with ILNumerics and IronPython</span> <span class="meta-nav">&#8594;</span></a></p>
<p>The post <a rel="nofollow" href="https://ilnumerics.net/blog/plotting-fun-with-ilnumerics-and-ironpython/">Plotting Fun with ILNumerics and IronPython</a> appeared first on <a rel="nofollow" href="https://ilnumerics.net/blog">The ILNumerics Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Since the early days of IronPython, I keep shifting one bullet point down on my ToDo list:</p>
<p>* Evaluate options to use <a href="http://ilnumerics.net">ILNumerics</a> from IronPython</p>
<p>Several years ago there has been some attempts from<a href="https://code.google.com/p/ironlab/"> ILNumerics users</a> who successfully utilized ILNumerics from within IronPython. But despite our fascination for these attempts, we were not able to catch up and deeply evaluate all options for joining both projects. Years went by and Microsoft has dropped support for IronPython in the meantime. Nevertheless, a considerably large community seems to be active on IronPython. Finally, today is the day I am going to give this a first quick shot.</p>
<p><span id="more-599"></span></p>
<p><em>Disclaimer: I am not a python developer. My experience with IronPython range from 0 &#8230; zero (unfortunatley, since the project deserves <strong>much</strong> more attention). For CPython it is only slighly better. So please bare with me if I went into some stupid direction or if I have completely missed better options in this article! Corrections and suggestions are always warmly welcome.</em></p>
<h1>Setup</h1>
<p>I downloaded and installed <a href="https://ironpython.codeplex.com/releases/view/90087">IronPython from CodePlex</a>. Also, in Visual Studio 2013 there exists a link in the NEW PROJECT dialog advertising the download of IronPython Tools for Visual Studio. I used that to setup Visual Studio for IronPython projects. All setup went smooth and easy. Nice!</p>
<h1>Creating Plots with IronPython</h1>
<p>The challenge I was interested in the most was how it is possible to utilize the great plotting capabilities of <a href="http://ilnumerics.net/Visualization-API.html">ILNumerics Visualization Engine</a> from IronPython projects. Since matplotlib seems not to be available for IronPython and other alternatives are also pretty rare (if any at all?) having our visualization engine available to IronPython projects seem to be a big improvement.</p>
<p>The good news first: it works and it does so very easily. The following plot is done purely in IronPython:</p>
<p><a href="http://ilnumerics.net/blog/wp-content/uploads/2014/09/Plotting-Fun-with-ILNumerics-in-IronPython1.png"><img class="aligncenter size-full wp-image-613" src="http://ilnumerics.net/blog/wp-content/uploads/2014/09/Plotting-Fun-with-ILNumerics-in-IronPython1.png" alt="" width="661" height="470" /></a>I started with a fresh new Iron Python Windows Forms Application from the &#8216;New Project&#8217; dialog in Visual Studio 2013.</p>
<p><a href="http://ilnumerics.net/blog/wp-content/uploads/2014/09/IronPython_ILPanel_NewProjectVS2013.png"><img src="http://ilnumerics.net/blog/wp-content/uploads/2014/09/IronPython_ILPanel_NewProjectVS2013.png" alt="" width="662" height="384" /></a></p>
<p>This gives a template python file &#8216;IronPython_ILPanel.py&#8217; with the following content:</p>
<pre class="brush: python; title: ; notranslate">
import clr
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')

from System.Drawing import *
from System.Windows.Forms import *

class MyForm(Form):
    def __init__(self):
        # Create child controls and initialize form
        pass

Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)

form = MyForm()
Application.Run(form)</pre>
<p>If you are familiar with the common setup of Windows Forms you may notice some similarities with the stub provided by a new C# Windows Forms Application project. What is otherwise spread over multiple files, now is done all within the global scope of the one and only *.py file: the form class is defined, the static Application class is configured and the event loop is started with an instance of the formerly defined MyForm class. Straight. This corresponds to the common setup for Windows.Forms from any language, where no Designer support exists for. The same could be done in PowerShell, to name just another example.</p>
<p>In order to integrate support for ILNumerics Visualization Engine, I did the following simple steps:</p>
<p>1) If not done so far, go and install <a href="http://ilnumerics.net">ILNumerics Ultimate VS</a>. We offer <a href="http://ilnumerics.net/download.html">30 days trials</a> which contain all features without limitation.<br />
2) Once installed, ILNumerics is available in the &#8220;Add Reference&#8221; dialog (right click on References in the Solution Explorer). ILNumerics.dll is added from the .NET tab:</p>
<p><a href="http://ilnumerics.net/blog/wp-content/uploads/2014/09/IronPython_ILPanel_Select_Component.png"><img class="aligncenter size-full wp-image-606" src="http://ilnumerics.net/blog/wp-content/uploads/2014/09/IronPython_ILPanel_Select_Component.png" alt="" width="592" height="476" /></a>3) Make the ILNumerics namespaces available: I added the following lines to the import section at the very top of IronPython_ILPanel.py:</p>
<pre class="brush: python; title: ; notranslate">
import clr
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
clr.AddReference('ILNumerics')

from System.Drawing import *
from System.Windows.Forms import *
from ILNumerics import *
from ILNumerics.Drawing import *
from ILNumerics.Drawing.Plotting import *
</pre>
<p>4) Now we are ready to add a plot to the form. In C# we would simply use the <code>ilPanel1_Load</code> event handler which is easily added by help of the forms designer. Since we do not have designer support here, we simply add the setup to the constructor of MyForm:</p>
<pre class="brush: python; title: ; notranslate">
class MyForm(Form):
   def __init__(self):
     # Create child controls and initialize form
     ilpanel = ILPanel()
     ilpanel.Dock = DockStyle.Fill
     self.Controls.Add(ilpanel)
     # show some demo: first create a plotcube
     pc = ILPlotCube(&quot;pc&quot;, 0)
     # it will hold a surface with some sinc data in 3D
     # You can use ILRetArray returned from any ILNumerics Computing
     # Module as input argument here directly. Type conversions seem to happen automatically.
     sf = ILSurface(ILSpecialData.sincf(40,50))
     pc.Add(sf)
     # add the plotcube to the scene
     ilpanel.Scene.Add(pc)
     self.Text = &quot;Plotting Fun with ILNumerics in IronPython&quot;
</pre>
<p>This is all straightforward. The configuration of the panel and the plots is exactly as it would have been done in C# or Visual Basic. However, we have to add the ILPanel to the self.Controls collection manually. The result, of course is exactly the same: a nice interactive form, utilizing OpenGL, with all manipulation options like rotation, pan and zoom. The full spectrum of the Visualization Engine should work out of the box. This includes several, flexible <a href="http://ilnumerics.net/plotting-api.html">3D and 2D plotting types</a> as well as the whole <a href="http://ilnumerics.net/scene-graph-shapes-and-buffers.html">scene graph functionality</a> for building your own interactive visualizations.</p>
<p>This is all what needs to be done in order to create nice professional plots directly within IronPython. Press F5 and start your application, rotate the plot with the mouse and learn about all the <a href="http://ilnumerics.net/visualization-engine.html">options you have</a>.</p>
<p><iframe width="474" height="267" src="https://www.youtube.com/embed/G9WWy_u-vvI?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<h1>Computing Fun with IronPython and ILNumerics</h1>
<p>ILNumerics not only rely on its own flexible n-dimensional array implementation, it also introduces its very own memory management &#8211; for <a href="http://ilnumerics.net/performance.html">very good reasons</a>. In order for the memory managements to work, <a href="http://ilnumerics.net/GeneralRules.html">individual array types</a> (ILArray, ILInArray, ILOutArray and ILRetArray) are used in ILNumerics algorithms. This makes great use of the strict type safety of .NET languages as C# and Visual Basic and of automatic conversions between those types.</p>
<p>Python on the other side is a dynamic language. It does not know the concept of types to the same extend. A straightforward application of the ILNumerics array types is not possible. IronPython, however offers workarounds (clr.Convert) but they are not able to provide the same syntactical convenience as a pure C# algorithm.</p>
<p>My recommendation for the utilization of ILNumerics Computing Engine therefore is as follows:</p>
<p>ILNumerics Computing Engine can be used without restriction. The utilization of existing algorithms is straightforward. Algorithms leveraging the ILNumerics Function Rules can be called directly without any type conversions. The creation of local variables on the other side requires type conversions from ILRetArray to ILArray. This can be done by help of IronPythons clr.Convert function.</p>
<p>The type conversion issue possibly makes it less feasible to write own ILNumerics Computing Engine algorithms in IronPython. But most the time, one would rather want to use existing python algorithms anyway. In order to actually create a new algorithm, one should rather utilize C# and compile the algorithm into its own .NET module which can than easily be imported into your python project and get interfaced from your python code.</p>
<h1>Summary</h1>
<p>This blog demonstrated how easy it is to utilize ILNumerics from IronPython. Especially the Visualization Engine is incorporated without any problems and offers the full set of visualization and plotting options out of the box. Algorithms created with ILNumerics Computation Engine can directly be interfaced and used &#8211; in parallel with numpy algorithms, if the need arise. The syntax of the Computing Engine however is not as expressive and more clumsy due to the absense of implicit type conversions and operator overloads. Complex algorithms one therefore would rather implement in C# or VisualBasic than in IronPython. For small algorithms, like data preprocessing and the like, ILNumerics Computing Engine serves as a faster alternative to numpy arrays.</p>
<p>The post <a rel="nofollow" href="https://ilnumerics.net/blog/plotting-fun-with-ilnumerics-and-ironpython/">Plotting Fun with ILNumerics and IronPython</a> appeared first on <a rel="nofollow" href="https://ilnumerics.net/blog">The ILNumerics Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://ilnumerics.net/blog/plotting-fun-with-ilnumerics-and-ironpython/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Fast. Faster …. Performance Comparison: C# (ILNumerics), FORTRAN, MATLAB and numpy – Part II</title>
		<link>https://ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-ii/</link>
		<comments>https://ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-ii/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 16:51:38 +0000</pubDate>
		<dc:creator><![CDATA[haymo]]></dc:creator>
				<category><![CDATA[Comparison]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[fortran]]></category>
		<category><![CDATA[ILNumerics]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[plots]]></category>
		<category><![CDATA[test setup]]></category>

		<guid isPermaLink="false">http://ilnumerics.net/blog/?p=52</guid>
		<description><![CDATA[<p>In the first part of my somehow lengthy comparison between Fortran, ILNumerics, Matlab and numpy, I gave some categorization insight into terms related to &#8216;performance&#8217; and &#8216;language&#8217;. This part explains the setup and hopefully the results will fit in here as well (otherwise we&#8217;ll need a third part ) Prerequisites This comparison is going to &#8230; <a href="https://ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-ii/" class="more-link">Continue reading <span class="screen-reader-text">Fast. Faster …. Performance Comparison: C# (ILNumerics), FORTRAN, MATLAB and numpy – Part II</span> <span class="meta-nav">&#8594;</span></a></p>
<p>The post <a rel="nofollow" href="https://ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-ii/">Fast. Faster …. Performance Comparison: C# (ILNumerics), FORTRAN, MATLAB and numpy – Part II</a> appeared first on <a rel="nofollow" href="https://ilnumerics.net/blog">The ILNumerics Blog</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In the <a href="http://ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-i/">first part</a> of my somehow lengthy comparison between Fortran, ILNumerics, Matlab and numpy, I gave some categorization insight into terms related to &#8216;performance&#8217; and &#8216;language&#8217;. This part explains the setup and hopefully the results will fit in here as well (otherwise we&#8217;ll need a third part <img src="https://ilnumerics.net/blog/wp-includes/images/smilies/icon_neutral.gif" alt=":|" class="wp-smiley" /> )</p>
<h2>Prerequisites</h2>
<p>This comparison is going to be easy and fair! This means, we will not attempt to compare an apple with the same apple, wrapped in a paper bag (like often done with the MKL) nor are we going to use specific features of an individual language/ framework &#8211; just to outperform another framework (like using datastructures which are better handled in a OOP language, lets say complicated graph structures or so).</p>
<p>We rather seek for an algorithm of:</p>
<ul>
<li>Sufficient size and complexity. A simple binary function like BLAS: DAXPY is not sufficient here, since it would neglect the impact of the memory management &#8211; a very important factor in .NET.</li>
<li>Limited size and complexity in order to be able to implement the algorithm on all frameworks compared (in a reasonable time).</li>
</ul>
<p>We did chose the <a title="wikipedia: kmeans" href="http://en.wikipedia.org/wiki/Kmeans" target="_blank">kmeans </a>algorithm. It only uses common array syntax, no calls to linear algebra routines (which are usually implemented in Intel&#8217;s MKL among all frameworks) and &#8211; used on reasonable data sizes &#8211; comes with sufficient complexity, computational and memory demands. That way we can measure the true performance of the framework, its array implementation and the feasibility of the mathematical syntax.</p>
<p>Two versions of kmeans were implemented for every framework: A &#8216;natural&#8217; version which is able to be translated into all languages with minimal differences according execution cost. A second version allows for obvious optimizations to get applied to the code according the language recommendations where applicable. All &#8216;more clever&#8217; optimizations are left to the corresponding compiler/interpreter.</p>
<p>The test setup: Acer TravelMate 8472TG, Intel Core™ i5-450M processor 2.4GHz, 3MB L3 cache, 4GB DDR3 RAM, Windows 7/64Bit. All tests were targeting the x86 platform.</p>
<h2>ILNumerics Code</h2>
<p>The printout of the ILNumerics variant for the kmeans algorithm is shown. The code demonstrates only obligatory features for memory management: Function and loop scoping and specific typed function parameters. For clarity, the function parameter checks and loop parameter initialization parts have been abbreviated.</p>
<pre class="brush: csharp; title: ; notranslate">public static ILRetArray&lt;double&gt; kMeansClust (ILInArray&lt;double&gt; X, 
                                             ILInArray&lt;double&gt; k,
                                             int maxIterations, 
                                             bool centerInitRandom,
                                             ILOutArray&lt;double&gt; outCenters) {
   using (ILScope.Enter(X, k)) {

// … (abbreviated: parameter checking, center initializiation)

while (maxIterations --&gt; 0) {
    for (int i = 0; i &lt; n; i++) {
        using (ILScope.Enter()) {
            ILArray&lt;double&gt; minDistIdx = empty(); 
            min(sum(abs(centers - X[full,i])), minDistIdx,1).Dispose();// **
            classes[i] = minDistIdx[0]; 
        }
    }
    for (int i = 0; i &lt; iK; i++) {
        using (EnterScope()) {
            ILArray&lt;double&gt; inClass = X[full,find(classes == i)]; 
            if (inClass.IsEmpty) {
                centers[full,i] = double.NaN;
            } else {
                centers[full,i] = mean(inClass,1);
            }
        }
    }
    if (allall(oldCenters == centers)) break; 
    oldCenters.a = centers.C; 
}
if (!object.Equals(outCenters, null))
    outCenters.a = centers; 
return classes; 
   }

}</pre>
<p>The algorithm iteratively assigns data points to cluster centres and recalculates the centres according to its members afterwards. The first step needs n * m * k * 3 ops, hence its effort is O(nmk). The second step only costs O(kn + mn), hence the first loop clearly dominates the algorithm. A version better taking into account available ILNumerics features, would replace the line marked with ** by the following line: </p>
<pre class="brush: csharp; title: ; notranslate">...
min(distL1(centers, X[full, i]), minDistIdx, 1).Dispose();
...</pre>
<p>The distL1 function basically removes the need for multiple iterations over the same distance array by condensing the element subtraction, the calculation of the absolute values and its summation into one step for every centre point.</p>
<h2>Matlab® Code</h2>
<p>For the Matlab implementation the following code was used. Note, the existing kmeans algorithm in the stats toolbox has not been utilized, because it significantly deviates from our simple algorithm variant by more configuration options and inner functioning.</p>
<pre class="brush: matlabkey; title: ; notranslate">
function [centers, classes] = kmeansclust (X, k, maxIterations, 
  centerInitRandom)

% .. (parameter checking and initialization abbreviated)
 
while (maxIterations &gt; 0)
        maxIterations = maxIterations - 1; 
        for i = 1:n
            dist = centers - repmat(X(:,i),1,k); % ***
            [~, minDistIdx] = min(sum(abs(dist)),[], 2);           
            classes(i) = minDistIdx(1); 
        end
        for i = 1:k
            inClass = X(:,classes == i); 
            if (isempty(inClass))
                centers(:,i) = nan;
            else
                centers(:,i) = mean(inClass,2);
                inClassDiff = inClass - repmat(centers(:,i),1,size(inClass,2)); 
            end
        end
        if (all(all(oldCenters == centers))) 
            break;
        end
        oldCenters = centers; 
 end
</pre>
<p>Again, a version better matching the performance recommendations for the language would prevent the repmat operation and reuse the single column of X for all centres in order to calculate the difference between the centres and the current data point.</p>
<pre class="brush: matlabkey; title: ; notranslate">...
dist = bsxfun(@minus,centers,X(:,i));
...</pre>
<h2>FORTRAN Code</h2>
<p>In order to match our algorithm most closely, the first FORTRAN implementation simulates the optimized <code>bsxfun</code> variant of Matlab and the common vector expansion in ILNumerics accordingly. The array of distances between the cluster centres and the current data point is pre-calculated for each iteration of i: </p>
<pre class="brush: xml; title: ; notranslate">subroutine SKMEANS(X,M,N,IT,K,classes) 
!USE KERNEL32
  !DEC$ ATTRIBUTES DLLEXPORT::SKMEANS 

  ! DUMMIES
  INTEGER :: M,N,K,IT
  DOUBLE PRECISION, INTENT(IN) :: X(M,N)
  DOUBLE PRECISION, INTENT(OUT) :: classes(N)
  ! LOCALS 
  DOUBLE PRECISION,ALLOCATABLE :: centers(:,:) &amp;
                   ,oldCenters(:,:) &amp;
                   ,distances(:) &amp; 
                   ,tmpCenter(:) &amp; 
                   ,distArr(:,:)
  DOUBLE PRECISION nan
  INTEGER S, tmpArr(1)
  
  nan = 0
  nan = nan / nan
  
  ALLOCATE(centers(M,K),oldCenters(M,K),distances(K),tmpCenter(M),distArr(M,K))

  centers = X(:,1:K)  ! init centers: first K data points
  do  
    do i = 1, N       ! for every sample...
        do j = 1, K   ! ... find its nearest cluster
            distArr(:,j) = X(:,i) - centers(:,j)         ! **
        end do
        distances(1:K) = sum(abs(distArr(1:M,1:K)),1)    
        tmpArr = minloc ( distances(1:K) )
        classes(i) = tmpArr(1);
    end do
  
    do j = 1,K ! for every cluster 
        tmpCenter = 0; 
        S = 0; 
        do i = 1,N ! compute mean of all samples assigned to it
            if (classes(i) == j) then
                tmpCenter = tmpCenter + X(1:M,i); 
                S = S + 1; 
            end if     
        end do
        if (S &amp;gt; 0) then 
            centers(1:M,j) = tmpCenter / S; 
        else 
            centers(1:M,j) = nan;
        end if 
    end do
    
    if (IT .LE. 0) then ! exit condition
        exit; 
    end if 
    IT = IT - 1; 
    if (sum(sum(centers - oldCenters,2),1) == 0) then
        exit;  
    end if 
    oldCenters = centers; 
  end do
  DEALLOCATE(centers, oldCenters,distances,tmpCenter);
end subroutine SKMEANS</pre>
<p>Another version of the first step was implemented which utilizes the memory accesses more efficiently. Its formulation relatively closely matches the ‘optimized’ version of ILNumerics: </p>
<pre class="brush: xml; title: ; notranslate">
    ...
    do i = 1, N          ! for every sample...
        do j = 1, K      ! ... find its nearest cluster
            distances(j) = sum(                                &amp;
                                abs(                           &amp;
                                    X(1:M,i) - centers(1:M,j)))
        end do

        tmpArr = minloc ( distances(1:K) )
        classes(i) = tmpArr(1);
    
    end do
    ...
</pre>
<h2>numpy Code</h2>
<p>The general variant of the kmeans algorithm in numpy is as follows:</p>
<pre class="brush: python; title: ; notranslate"> 
from numpy import *

def kmeans(X,k):
    n = size(X,1)
    maxit = 20
    centers = X[:,0:k].copy()
    classes = zeros((1.,n))
    oldCenters = centers.copy()
    for it in range(maxit):
        for i in range(n):
            dist = sum(abs(centers - X[:,i,newaxis]), axis=0)
            classes[0,i] = dist.argmin()
            
        for i in range(k):
            inClass = X[:,nonzero(classes == i)[1]]
            if inClass.size == 0:
                centers[:,i] = np.nan
            else:
                centers[:,i] = inClass.mean(axis=1)

        if all(oldCenters == centers):
            break
        else:
            oldCenters = centers.copy()
</pre>
<p>Since this framework showed the slowest execution speed of all implemented frameworks in the comparison (and due to my limited knowledge of numpys optimization recommendations) no improved version was sought.</p>
<h2>Parameters</h2>
<p>The 7 algorithms described above were all tested against the same data set of corresponding size. Test data were evenly distributed random mumbers, generated on the fly and reused for all implementations. The problem sizes m and n and the number of clusters k are varied according the following table: </p>
<pre>
	min value 	max value	fixed parameters
m	50		2000		n = 2000, k = 350
n	400		3000		m = 500, k = 350
k	10		1000		m = 500, n = 2000
</pre>
<p>By varying one value, the other variables were fixed respectively.<br />
The results produced by all implementations were checked for identity. Each test was repeated 10 times (5 times for larger datasets) and the average of execution times were taken as test result. Minimum and maximum execution times were tracked as well.  </p>
<h2>Results</h2>
<p>Ok, I think we make it to the results in this part! <img src="https://ilnumerics.net/blog/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /> The plots first! The runtime measures are shown in the next three figures as error bar plots:<br />
<figure id="attachment_68" style="width: 688px;" class="wp-caption aligncenter"><a href="http://ilnumerics.net/blog/wp-content/uploads/2012/02/plotall4k.png"><img src="http://ilnumerics.net/blog/wp-content/uploads/2012/02/plotall4k-1024x768.png" alt="" width="688" height="516" class="size-large wp-image-68" /></a><figcaption class="wp-caption-text">Execution speed comparison for variying k</figcaption></figure><br />
<figure id="attachment_67" style="width: 688px;" class="wp-caption aligncenter"><a href="http://ilnumerics.net/blog/wp-content/uploads/2012/02/plotall4m.png"><img src="http://ilnumerics.net/blog/wp-content/uploads/2012/02/plotall4m-1024x768.png" alt="" width="688" height="516" class="size-large wp-image-67" /></a><figcaption class="wp-caption-text">Execution speed comparison for variying m</figcaption></figure><br />
<figure id="attachment_66" style="width: 688px;" class="wp-caption aligncenter"><a href="http://ilnumerics.net/blog/wp-content/uploads/2012/02/plotall4n.png"><img src="http://ilnumerics.net/blog/wp-content/uploads/2012/02/plotall4n-1024x768.png" alt="" width="688" height="516" class="size-large wp-image-66" /></a><figcaption class="wp-caption-text">Execution speed comparison for variying n</figcaption></figure><br />
 Clearly, the numpy framework showed the worst performance – at least we did not implement any optimization for this platform. MATLAB, as expected, shows similar (long) execution times. In the case of the unoptimized algorithms, the ILNumerics implementation is able to almost catch up with the execution speed of FORTRAN. Here, the .NET implementation needs less than twice the time of the first, naïve FORTRAN algorithm. The influence of the size of n is negligible, since the most ‘work’ of the algorithm is done by calculating the distances of one data point to all cluster centres. Therefore, only the dimensionality of the data and the number of clusters are important here.  </p>
<h2>Conclusion</h2>
<p>For the optimized versions of kmeans (the stippled lines in the figures) – especially for middle sized and larger data sets (k &gt; 200 clusters or m &gt; 400 dimensions) – the ILNumerics implementation runs at the same speed as the FORTRAN one. This is due to ILNumerics implementing similar optimizations into its builtin functions as the FORTRAN compiler does. Also, the efforts of circumventing around the GC by the ILNumerics memory management and preventing from bound checks in inner loops pay off here. However, there is still potential for future speed-up, since SSE extensions are (yet) not utilized.<br />
For smaller data sets, the overhead of repeated creation of ILNumerics arrays becomes more important, which will be another target for future enhancements. Clearly visible from the plots is the high importance of the choice of algorithm. By reformulating the inner working loop, a significant improvement has been achieved for all frameworks. </p>
<p>The post <a rel="nofollow" href="https://ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-ii/">Fast. Faster …. Performance Comparison: C# (ILNumerics), FORTRAN, MATLAB and numpy – Part II</a> appeared first on <a rel="nofollow" href="https://ilnumerics.net/blog">The ILNumerics Blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-ii/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
