Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# how can I sidestep the memory allocation bottleneck to improve multithreading performance

I use C# as a research tool, and frequently need to run CPU intensive tasks such as optimisations. In theory I should be able to get big performance improvements by multi-threading my code, but in practice when I use the same number of threads as the number of cores available on my workstation I usually find that the CPU is still only running at 25%-50% of max. Interrupting the code to see what all the threads are doing strongly suggests that memory allocation is the bottleneck, because most threads will be waiting for new statements to execute.

One solution would be to try and re-engineer all my code to be much more memory efficient, but that would be a big and time-consuming task. However, since I have an abundance of memory on my workstation, I'm wondering if I can sidestep this problem by setting up the different threads so that they each have their own private pool of memory to work from. Of course, some objects will still need to be public between all threads, otherwise it won't be possible to specify the tasks for each thread or to harvest the results.

Does anyone know if this kind of approach is possible in C#, and if so, how should I go about it?

like image 389
Stochastically Avatar asked Mar 22 '23 21:03

Stochastically


1 Answers

If you has memory allocation bottleneck, you should:

  1. Use "objects pool" (as @MartinJames said). Initialize objects pool, when application is started. Objects pool should improve performance of heap allocation.

  2. Use structs (or any value type), as local variables, because stack allocation is much faster than heap.

  3. Avoid implicit memory allocation. For example, when you add item into List<>:

    If Count already equals Capacity, the capacity of the List is increased by automatically reallocating the internal array, and the existing elements are copied to the new array before the new element is added (source MSDN).

  4. Avoid boxing. It's very expensive:

    In relation to simple assignments, boxing and unboxing are computationally expensive processes. When a value type is boxed, a new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally. (source MSDN)

  5. Avoid lambda expressions which captures a variable (because new object will be created for captured variable)

like image 165
oakio Avatar answered Apr 23 '23 15:04

oakio