Parallel.For vs BackgroundWorker
A number of jobs I get are fairly processor intensive so I decided to take a look at .Net’s new Parallel library, wondering how performant it’d be in my (not necessarly your) environment. Implementation is fairly straightforward, with a minor lambda expression.
My busy routine copies an array to a SQL server. The array is 8 columns by 10,000 rows. The columns are strings, each column has it’s own sql table, I ‘normalize’ these columns first. Each column ‘normalization’ being a seperate process.
The SQL server is on the same machine as the running application. (i7-2670M,8GB,SSD,Win7 on VMWare Workstation)
Speed. (Times are an average of five runs)
// Single threaded: Normalization time: 00:03:33.33
// Background worker (5 async threads): Normalization time: 00:02:31.39
// 4 processors, Parallel: Normalization time: 00:03:15.30
// 2 processors, Parallel: Normalization time: 00:04:05.59
Suprisingly, the Parallel.For library was significantly slower (24%) than BGW on a four processor machine. CPU utilization did not exceed 41% for any of the tests. It looks like the extra abstraction layer, whereas convinient, adds a fair amount of time to the tests.
Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); //// Single threaded //// Normalization time: 00:03:33.33 //NormalizeColumn(new NormalizationState(2, "Name", false)); //NormalizeColumn(new NormalizationState(3, "Voltage", true)); //NormalizeColumn(new NormalizationState(4, "Equipment", true)); //NormalizeColumn(new NormalizationState(5, "Type", true)); //NormalizeColumn(new NormalizationState(6, "Zone", true)); //// Background worker //// Normalization time: 00:02:31.39 //bwThreadCount = 0; //foreach (BackgroundWorker w in bw) //{ // w.WorkerReportsProgress = false; // w.WorkerSupportsCancellation = false; // w.DoWork += new DoWorkEventHandler(BusyWork); // w.RunWorkerAsync(new NormalizationState(bwThreadCount + 2, names[bwThreadCount], states[bwThreadCount])); // bwThreadCount++; // Thread.Sleep(100); //} //while (bwThreadCount > 0) Thread.Sleep(15000); // 4 processors, Parallel // Normalization time: 00:03:15.30 // 2 processors, Parallel // Normalization time: 00:04:05.59 Parallel.For(2, 7, p => { switch (p) { case 2: NormalizeColumn(new NormalizationState(2, "Name", false)); break; case 3: NormalizeColumn(new NormalizationState(3, "Voltage", true)); break; case 4: NormalizeColumn(new NormalizationState(4, "Equipment", true)); break; case 5: NormalizeColumn(new NormalizationState(5, "Type", true)); break; case 6: NormalizeColumn(new NormalizationState(6, "Zone", true)); break; } }); TimeSpan ts = stopWatch.Elapsed; string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine(" Normalization time: " + elapsedTime);
Leave a Reply