{"id":119,"date":"2008-04-29T07:12:38","date_gmt":"2008-04-29T12:12:38","guid":{"rendered":"http:\/\/mariusbancila.ro\/blog\/?p=119"},"modified":"2008-04-29T12:20:08","modified_gmt":"2008-04-29T17:20:08","slug":"parallelfx-saves","status":"publish","type":"post","link":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/","title":{"rendered":"ParallelFX Saves!"},"content":{"rendered":"<p>After the MVP Summit in Seattle, I started to dig into the Parallel FX framework (currently under a CTP available <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyID=e848dc1d-5be3-4941-8705-024bc7f180ba&#038;displaylang=en\" target=\"_blank\">here<\/a>). In just a few words, the framework is composed of:<\/p>\n<ul>\n<li>Task Parallel Library (TPL), that provides means to manage task (i.e. units of execution), and exposes a<\/li>\n<li>TPL API, represented by the static function in the Parallel class: For, ForEach and Do<\/li>\n<li>Parallel LINQ (PLINQ): allows parallelization of LINQ queries (AsParallel)\n<\/ul>\n<p>Since I have a 2 codes CPU (AMP Athlon 64 X2 Dual) I wanted to see how much performance do I actually gain by parallelizing loops. So I benchmarked matrices multiplication and arrays sorting.<\/p>\n<h3>Matrices Multiplication<\/h3>\n<p>Having this Matrix class:<\/p>\n<pre class=\"prettyprint\">\r\nclass Matrix&lt; T &gt;\r\n{\r\n    private T[,] _values;\r\n\r\n    public int Rows { get; private set; }\r\n    public int Columns { get; private set; }\r\n\r\n    public T this[int row, int column]\r\n    {\r\n        get { return _values[row, column]; }\r\n        set { _values[row, column] = value; }  \r\n    }\r\n\r\n    public Matrix(int rows, int columns)\r\n    {\r\n        if (rows &lt; 1) throw new ArgumentOutOfRangeException(\"rows\");\r\n        if (columns &lt; 1) throw new ArgumentOutOfRangeException(\"columns\");\r\n        Rows = rows;\r\n        Columns = columns;\r\n        _values = new T[rows, columns];\r\n    }\r\n}\r\n<\/pre>\n<p>I could write the multiplication routine like this:<\/p>\n<pre class=\"prettyprint\">\r\npublic static Matrix&lt; double &gt; MultiplySequential(Matrix&lt; double&gt; m1, Matrix&lt; double &gt; m2)\r\n{\r\n    if (m1.Columns != m2.Rows)\r\n         throw new ArgumentException(\"incorrect matrix size\", \"m2\");\r\n\r\n    Matrix&lt; double &gt; result = new Matrix&lt; double &gt;(m1.Rows, m2.Columns);\r\n    for (int i = 0; i &lt; m1.Rows; i++)\r\n    {\r\n        for (int j = 0; j &lt; m2.Columns; j++)\r\n        {\r\n            result[i, j] = 0;\r\n            for (int k = 0; k &lt; m1.Columns; k++)\r\n            {\r\n                result[i, j] += m1[i, k] * m2[k, j];\r\n            }\r\n         }\r\n    }\r\n    return result;\r\n}\r\n<\/pre>\n<p>Modifying the function to use Parallel.For was pretty simple, since this is very straight forward:<\/p>\n<pre class=\"prettyprint\">\r\npublic static Matrix&lt; double &gt; MultiplyParallel(Matrix&lt; double&gt; m1, Matrix&lt; double &gt; m2)\r\n{\r\n    if (m1.Columns != m2.Rows)\r\n        throw new ArgumentException(\"incorrect matrix size\", \"m2\");\r\n\r\n    Matrix&lt; double &gt; result = new Matrix&lt; double &gt;(m1.Rows, m2.Columns);\r\n    Parallel.For(\r\n        0,\r\n        m1.Rows,\r\n        i =&gt;\r\n        {\r\n            for (int j = 0; j &lt; m2.Columns; j++)\r\n            {\r\n                result[i, j] = 0;\r\n                for (int k = 0; k &lt; m1.Columns; k++)\r\n                {\r\n                    result[i, j] += m1[i, k] * m2[k, j];\r\n                }\r\n            }\r\n        });\r\n\r\n    return result;\r\n}\r\n<\/pre>\n<p>I used matrices of various sizes, started from 100&#215;100 to 1000&#215;1000 and compared the execution time for the sequential version or the parallel version.<\/p>\n<pre class=\"prettyprint\">\r\nfor(int SIZE = 100; SIZE &lt;= 1000; SIZE += 100)\r\n{\r\n    Console.WriteLine(\"Matrices size: {0}x{0}\", SIZE);\r\n\r\n    Matrix&lt; double &gt; m1 = MatrixOperations.GenerateRandom(SIZE, SIZE);\r\n    Matrix&lt; double &gt; m2 = MatrixOperations.GenerateRandom(SIZE, SIZE);\r\n    \r\n    Console.Write(\"Sequential...\\t\");\r\n    DateTime starts = DateTime.Now;\r\n    Matrix&lt; double &gt; ms = MatrixOperations.MultiplySequential(m1, m2);\r\n    Console.WriteLine(\"{0}\", DateTime.Now - starts);\r\n\r\n    Console.Write(\"Parallel...\\t\");\r\n    DateTime startp = DateTime.Now;\r\n    Matrix&lt; double &gt; mp = MatrixOperations.MultiplyParallel(m1, m2);\r\n    Console.WriteLine(\"{0}\", DateTime.Now - startp);\r\n}\r\n<\/pre>\n<p>The results were:<\/p>\n<pre class=\"console\">\r\nMatrices size: 100x100\r\nSequential...   00:00:00.0625000\r\nParallel...     00:00:00.0937500\r\nMatrices size: 200x200\r\nSequential...   00:00:00.4531250\r\nParallel...     00:00:00.2343750\r\nMatrices size: 300x300\r\nSequential...   00:00:01.4843750\r\nParallel...     00:00:00.7500000\r\nMatrices size: 400x400\r\nSequential...   00:00:03.7812500\r\nParallel...     00:00:02.0625000\r\nMatrices size: 500x500\r\nSequential...   00:00:07.8750000\r\nParallel...     00:00:04.1406250\r\nMatrices size: 600x600\r\nSequential...   00:00:14.3437500\r\nParallel...     00:00:07.2656250\r\nMatrices size: 700x700\r\nSequential...   00:00:23.4531250\r\nParallel...     00:00:11.7812500\r\nMatrices size: 800x800\r\nSequential...   00:00:36.1250000\r\nParallel...     00:00:18.4218750\r\nMatrices size: 900x900\r\nSequential...   00:00:51.5312500\r\nParallel...     00:00:25.8906250\r\nMatrices size: 1000x1000\r\nSequential...   00:01:11.5156250\r\nParallel...     00:00:35.6875000\r\n<\/pre>\n<p>They show that the time for executing the parallel version was only half the time for the sequential multiplication (remember that I have 2 cores). That means reducing the execution time, not 20 or 30%, but 50%, basically the maximum possible.<\/p>\n<h3>Array Sorting<\/h3>\n<p>For sorting the arrays I tested with the wost sorting algorithm: bubblesort. Here is the implementation:<\/p>\n<pre class=\"prettyprint\">\r\ninterface ISort&lt; T &gt;\r\n{\r\n    void SortSequential(T[] array);\r\n    void SortParallel(T[] array);\r\n}\r\n\r\nclass BubbleSort&lt; T &gt; : ISort&lt; T &gt;\r\n    where T: IComparable\r\n{\r\n    public void SortSequential(T[] array)\r\n    {\r\n        for(int i = 0; i &lt; array.Length; ++i)\r\n        {\r\n            for(int j = 0; j &lt; array.Length; ++j)\r\n            {\r\n                if(array[i].CompareTo(array[j]) &lt; 0)\r\n                {\r\n                    T aux = array[i];\r\n                    array[i] = array[j];\r\n                    array[j] = aux;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    public void SortParallel(T[] array)\r\n    {\r\n        Parallel.For(\r\n            0,\r\n            array.Length,\r\n            i =&gt;\r\n            {\r\n                for (int j = 0; j &lt; array.Length; ++j)\r\n                {\r\n                    if (array[i].CompareTo(array[j]) &lt; 0)\r\n                    {\r\n                        T aux = array[i];\r\n                        array[i] = array[j];\r\n                        array[j] = aux;\r\n                    }\r\n                }\r\n            });\r\n    }\r\n}\r\n<\/pre>\n<p>First, I tested that with small array, 100 to 1000 elements.<\/p>\n<pre class=\"prettyprint\">\r\nint STEP = 100;\r\nfor (int SIZE = STEP; SIZE <= STEP*20; SIZE += STEP)\r\n{\r\n    double[] array = GenerateRandomDoubles(SIZE);\r\n\r\n    ISort&lt; double &gt; sorter = new BubbleSort&lt; double &gt;();\r\n\r\n    Console.WriteLine(\"Array size: {0}\", SIZE);\r\n\r\n    Console.Write(\"Sequential...\\t\");\r\n    DateTime starts = DateTime.Now;\r\n    sorter.SortSequential(array);\r\n    Console.WriteLine(\"{0}\", DateTime.Now - starts);\r\n\r\n    Console.Write(\"Parallel...\\t\");\r\n    DateTime startp = DateTime.Now;\r\n    sorter.SortParallel(array);\r\n    Console.WriteLine(\"{0}\", DateTime.Now - startp);\r\n}\r\n<\/pre>\n<p>And the results were:<\/p>\n<pre class=\"console\">\r\nArray size: 100\r\nSequential...   00:00:00\r\nParallel...     00:00:00.0781250\r\nArray size: 200\r\nSequential...   00:00:00\r\nParallel...     00:00:00\r\nArray size: 300\r\nSequential...   00:00:00\r\nParallel...     00:00:00\r\nArray size: 400\r\nSequential...   00:00:00\r\nParallel...     00:00:00\r\nArray size: 500\r\nSequential...   00:00:00.0156250\r\nParallel...     00:00:00\r\nArray size: 600\r\nSequential...   00:00:00\r\nParallel...     00:00:00.0156250\r\nArray size: 700\r\nSequential...   00:00:00\r\nParallel...     00:00:00.0156250\r\nArray size: 800\r\nSequential...   00:00:00.0156250\r\nParallel...     00:00:00\r\nArray size: 900\r\nSequential...   00:00:00.0156250\r\nParallel...     00:00:00.0156250\r\nArray size: 1000\r\nSequential...   00:00:00.0312500\r\nParallel...     00:00:00.0156250\r\nArray size: 1100\r\nSequential...   00:00:00.0156250\r\nParallel...     00:00:00.0156250\r\nArray size: 1200\r\nSequential...   00:00:00.0312500\r\nParallel...     00:00:00.0312500\r\nArray size: 1300\r\nSequential...   00:00:00.0312500\r\nParallel...     00:00:00.0156250\r\nArray size: 1400\r\nSequential...   00:00:00.0468750\r\nParallel...     00:00:00.0312500\r\nArray size: 1500\r\nSequential...   00:00:00.0468750\r\nParallel...     00:00:00.0312500\r\nArray size: 1600\r\nSequential...   00:00:00.0468750\r\nParallel...     00:00:00.0312500\r\nArray size: 1700\r\nSequential...   00:00:00.0625000\r\nParallel...     00:00:00.0468750\r\nArray size: 1800\r\nSequential...   00:00:00.0625000\r\nParallel...     00:00:00.0468750\r\nArray size: 1900\r\nSequential...   00:00:00.0781250\r\nParallel...     00:00:00.0468750\r\nArray size: 2000\r\nSequential...   00:00:00.0937500\r\nParallel...     00:00:00.0468750\r\n<\/pre>\n<p>Then, I changed the for loop, so that it creates array from 5000 to 50000 elements. The results were:<\/p>\n<pre class=\"console\">\r\nArray size: 5000\r\nSequential...   00:00:00.5312500\r\nParallel...     00:00:00.4062500\r\nArray size: 10000\r\nSequential...   00:00:02.0468750\r\nParallel...     00:00:01.2500000\r\nArray size: 15000\r\nSequential...   00:00:04.5781250\r\nParallel...     00:00:02.7187500\r\nArray size: 20000\r\nSequential...   00:00:08.1562500\r\nParallel...     00:00:04.7187500\r\nArray size: 25000\r\nSequential...   00:00:12.7343750\r\nParallel...     00:00:07.5625000\r\nArray size: 30000\r\nSequential...   00:00:18.5468750\r\nParallel...     00:00:10.6406250\r\nArray size: 35000\r\nSequential...   00:00:25.4687500\r\nParallel...     00:00:14.5468750\r\nArray size: 40000\r\nSequential...   00:00:33.6562500\r\nParallel...     00:00:18.9531250\r\nArray size: 45000\r\nSequential...   00:00:42.7968750\r\nParallel...     00:00:23.8906250\r\nArray size: 50000\r\nSequential...   00:00:52.9218750\r\nParallel...     00:00:29.4687500\r\n<\/pre>\n<p>The  conclusion is that the parallel sorting is not efficient when the array size is less than 1000 elements; in other words there is no performance gain, but perhaps performance lost due to overhead of creating tasks and executing them and managing the context switching. The same conclusion is expressed in the framework's documentation:<\/p>\n<p><cite>Target areas of your program where algorithms are computationally expensive and\/or data sets are large (e.g. > 1000 elements). In such cases, there will likely be benefit to using parallelism.<\/cite><\/p>\n<p>That means, that when you parallelize an algorithm, you should take into consideration the size of the data structures it performs on, and unless a given threshold is not reached, a non-parallelized version should be used.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After the MVP Summit in Seattle, I started to dig into the Parallel FX framework (currently under a CTP available here). In just a few words, the framework is composed of: Task Parallel Library (TPL), that provides means to manage task (i.e. units of execution), and exposes a TPL API, represented by the static function &#8230; <a title=\"ParallelFX Saves!\" class=\"read-more\" href=\"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/\" aria-label=\"Read more about ParallelFX Saves!\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[11,20,42],"tags":[],"class_list":["post-119","post","type-post","status-publish","format-standard","hentry","category-csharp","category-ctps-betas","category-parallel-programming"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Marius Bancila\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Marius Bancila&#039;s Blog | About code. Mostly on C++\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"ParallelFX Saves!\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2008-04-29T12:12:38+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2008-04-29T17:20:08+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"ParallelFX Saves!\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#article\",\"name\":\"ParallelFX Saves!\",\"headline\":\"ParallelFX Saves!\",\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"},\"datePublished\":\"2008-04-29T07:12:38+02:00\",\"dateModified\":\"2008-04-29T12:20:08+02:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#webpage\"},\"articleSection\":\"C#, CTPs &amp; Betas, Parallel Programming\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"position\":2,\"name\":\"IT\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"position\":3,\"name\":\"Software\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/#listItem\",\"name\":\".NET\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/#listItem\",\"position\":4,\"name\":\".NET\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/csharp\\\/#listItem\",\"name\":\"C#\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/csharp\\\/#listItem\",\"position\":5,\"name\":\"C#\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/csharp\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#listItem\",\"name\":\"ParallelFX Saves!\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/#listItem\",\"name\":\".NET\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#listItem\",\"position\":6,\"name\":\"ParallelFX Saves!\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/net\\\/csharp\\\/#listItem\",\"name\":\"C#\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/\",\"name\":\"Marius Bancila\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Marius Bancila\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#webpage\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/\",\"name\":\"ParallelFX Saves!\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2008\\\/04\\\/29\\\/parallelfx-saves\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"datePublished\":\"2008-04-29T07:12:38+02:00\",\"dateModified\":\"2008-04-29T12:20:08+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"ParallelFX Saves!","description":"","canonical_url":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#article","name":"ParallelFX Saves!","headline":"ParallelFX Saves!","author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"},"datePublished":"2008-04-29T07:12:38+02:00","dateModified":"2008-04-29T12:20:08+02:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#webpage"},"isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#webpage"},"articleSection":"C#, CTPs &amp; Betas, Parallel Programming"},{"@type":"BreadcrumbList","@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog#listItem","position":1,"name":"Home","item":"https:\/\/mariusbancila.ro\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","position":2,"name":"IT","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","position":3,"name":"Software","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/#listItem","name":".NET"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/#listItem","position":4,"name":".NET","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/csharp\/#listItem","name":"C#"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/csharp\/#listItem","position":5,"name":"C#","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/csharp\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#listItem","name":"ParallelFX Saves!"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/#listItem","name":".NET"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#listItem","position":6,"name":"ParallelFX Saves!","previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/csharp\/#listItem","name":"C#"}}]},{"@type":"Organization","@id":"https:\/\/mariusbancila.ro\/blog\/#organization","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","url":"https:\/\/mariusbancila.ro\/blog\/"},{"@type":"Person","@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author","url":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/","name":"Marius Bancila","image":{"@type":"ImageObject","@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g","width":96,"height":96,"caption":"Marius Bancila"}},{"@type":"WebPage","@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#webpage","url":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/","name":"ParallelFX Saves!","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/#breadcrumblist"},"author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"creator":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"datePublished":"2008-04-29T07:12:38+02:00","dateModified":"2008-04-29T12:20:08+02:00"},{"@type":"WebSite","@id":"https:\/\/mariusbancila.ro\/blog\/#website","url":"https:\/\/mariusbancila.ro\/blog\/","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","inLanguage":"en-US","publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Marius Bancila's Blog | About code. Mostly on C++","og:type":"article","og:title":"ParallelFX Saves!","og:url":"https:\/\/mariusbancila.ro\/blog\/2008\/04\/29\/parallelfx-saves\/","article:published_time":"2008-04-29T12:12:38+00:00","article:modified_time":"2008-04-29T17:20:08+00:00","twitter:card":"summary","twitter:title":"ParallelFX Saves!"},"aioseo_meta_data":{"post_id":"119","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2021-03-18 21:13:46","updated":"2025-12-12 07:19:10","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"author_meta":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"featured_img":null,"jetpack_publicize_connections":[],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"uagb_comment_info":0,"uagb_excerpt":"After the MVP Summit in Seattle, I started to dig into the Parallel FX framework (currently under a CTP available here). In just a few words, the framework is composed of: Task Parallel Library (TPL), that provides means to manage task (i.e. units of execution), and exposes a TPL API, represented by the static function&hellip;","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/net\/csharp\/\" class=\"advgb-post-tax-term\">C#<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/ctps-betas\/\" class=\"advgb-post-tax-term\">CTPs &amp; Betas<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/parallel-programming\/\" class=\"advgb-post-tax-term\">Parallel Programming<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">C#<\/span>","<span class=\"advgb-post-tax-term\">CTPs &amp; Betas<\/span>","<span class=\"advgb-post-tax-term\">Parallel Programming<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 18 years ago","modified":"Updated 18 years ago"},"absolute_dates":{"created":"Posted on April 29, 2008","modified":"Updated on April 29, 2008"},"absolute_dates_time":{"created":"Posted on April 29, 2008 7:12 am","modified":"Updated on April 29, 2008 12:20 pm"},"featured_img_caption":"","series_order":"","jetpack_shortlink":"https:\/\/wp.me\/pYNdv-1V","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":0,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"wp:attachment":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}