Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#.net multithreading

I am experimenting on optimizing some mathematical operations using C#.net within a package called Grasshopper (part of Rhino3D). The operation is quite simple but the list on which it has to be performed is big and may get much bigger.

I am using Parallel.ForEach and lists in my C# script and the number of final results I get is lower than what is expected. This is most probably due to the fact that list.add is not thread safe (or not thread safe within the software I'm building it on top of).

  private void RunScript(double z, int x, List<double> y, ref object A)
  {
    List<double> temp = new List<double>();
    double r;
    System.Threading.Tasks.Parallel.ForEach(y, numb =>
      {
      r = Math.Pow((numb * x), z);
      temp.Add(r);
      });
    A = temp;

Please help me figure out a simple and efficient way of running this simple math operation over several hundreds of values using CPU multithreading (or if you have suggestions about GPU CUDA).

I hope that the obscure and specific software does not bother you because as far as I know it performs identically to normal C#.Net/Python/VB.Net.

like image 859
Dimitar Baldzhiev Avatar asked Apr 17 '15 21:04

Dimitar Baldzhiev


People also ask

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

What is C programming used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Why is C named so?

Quote from wikipedia: "A successor to the programming language B, C was originally developed at Bell Labs by Dennis Ritchie between 1972 and 1973 to construct utilities running on Unix." The creators want that everyone "see" his language. So he named it "C".

What is C of computer?

C is a high-level and general-purpose programming language that is ideal for developing firmware or portable applications. Originally intended for writing system software, C was developed at Bell Labs by Dennis Ritchie for the Unix Operating System in the early 1970s.


1 Answers

You surmise correctly, List<T> is not thread-safe. You must synchronize access to any instance of it.

One option is to simply synchronize in each task:

private void RunScript(double z, int x, List<double> y, ref object A)
{
    List<double> temp = new List<double>();
    object l = new object();
    System.Threading.Tasks.Parallel.ForEach(y, numb =>
    {
      double r = Math.Pow((numb * x), z);
      lock (l) temp.Add(r);
    });
    A = temp;
}

Note: your code had another bug in it also. You were sharing the same r variable amongst all the tasks, which could lead to the same value being added two or more times to the result, while other values were left out. I fixed the bug by simply moving the variable declaration to the body of the anonymous method used for the ForEach() call.


Another option is to recognize that you know in advance how many results you will have, and so can simply initialize an array large enough to contain all the results:

private void RunScript(double z, int x, List<double> y, ref object A)
{
    double[] results = new double[y.Count];
    System.Threading.Tasks.Parallel.For(0, y.Count, i =>
    {
      // read-only access of `y` is thread-safe:
      results[i] = Math.Pow((y[i] * x), z);
    });
    A = new List<double>(results);
}

No two threads will ever try to access the same element in the results array, and the array itself will never change (i.e. be reallocated), so this is perfectly thread safe.

The above assumes that you really do need a List<double> as the output object. Of course, if an array is satisfactory, then you can just assign results to A instead of passing it to the List<T> constructor to create a whole new object at the end.

like image 61
Peter Duniho Avatar answered Sep 23 '22 14:09

Peter Duniho