1
votes

I am working on a calculation intensive C# project that implements several algorithms. The problem is that when I want to profile my application, the time it takes for a particular algorithm varies. For example sometimes running the algorithm 100 times takes about 1100 ms and another time running 100 times takes much more time like 2000 or even 3000 ms. It may vary even in the same run. So it is impossible to measure improvement when I optimize a piece of code. It's just unreliable.

enter image description here

Here is another run:

enter image description here

So basically I want to make sure one CPU is dedicated to my app. The PC has an old dual core Intel E5300 CPU running on Windows 7 32 bit. So I can't just set process affinity and forget about one core forever. It would make the computer very slow for daily tasks. I need other apps to use a specific core when I desire and the when I'm done profiling, the CPU affinities come back to normal. Having a bat file to do the task would be a fantastic solution.

My question is: Is it possible to have a bat file to set process affinity for every process on windows 7?

PS: The algorithm is correct and every time runs the same code path. I created some object pool so after first run, zero memory is allocated. I also profiled memory allocation with dottrace and it showed no allocation after first run. So I don't believe GC is triggered when the algorithm is working. Physical memory is available and system is not running low on RAM.

Result: The answer by Chris Becke does the job and sets process affinities exactly as intended. It resulted in more uniform results specially when background apps like visual studio and dottrace are running. Further investigation into the divergent execution time revealed that the root for the unpredictability is CPU overheat. The CPU overheat alarm was off while the temperature was over 100C! So after fixing the malfunctioning fan, the results became completely uniform.

1
Never doctor a benchmark, that just produces optimistically good results that never reproduce in production. If you use double in your calculation code and you run it in 32-bit mode then you can get 3 distinct timings. Worst-case is a fat x3 slower than the best-case. Smells like that's what is happening. Remove the jitter forcing so it can run in 64-bit mode. Project > Properties > Build tab > Platform target = AnyCpu and Prefer 32-bit unticked. - Hans Passant
@HansPassant I checked the project settings and it is on Any CPU and the prefer 32bit is unchecked. I understand your point about not doctoring the benchmark. The problem I'm facing is that the same code execution time varies widely even in the same running session. On the screenshots it is shown that sometimes the execution time is different per invocation and sometimes it's nearly the same. I am not trying to achieve some artificial gain. I want a reliable and repeatable environment so every time I try optimizing a method, I know if it was making the code faster or slower. - morteza khosravi
Well, seems you have a 32-bit OS so those settings are not going to make any difference. If you can't get a 64-bit OS then just move on, it isn't going to get any prettier. Take the median and call it a day. - Hans Passant
@HansPassant I can install a 64 bit version. So if I install the 64-bit will the results be more predictable? I don't use double and long for calculation. Right now I'm scratching my head to figure out what affects my code's performance. Let me ask a very basic question. Suppose we have a very simple code like Fibonacci of a big number. If there is no allocation and no hyper-threading and the application is already running is it safe to say that if we call the algorithm multiple times, SHOULD the execution of each call be the same? - morteza khosravi

1 Answers

2
votes

You mean SetProcessAffinityMask?

I see this question, while tagged windows, is c#, so... I see the System.Diagnostics.Process object has a ThreadAffinity member that should perform the same function.

I am just not sure that this will stabilize the CPU times quite in the way you expect. A single busy task that is not doing IO should remain scheduled on the same core anyway unless another thread interrupts it, so I think your variable times are more due to other threads / processes interrupting your algorithm than the OS randomly shunting your thread to a different core - so unless you set the affinity for all other threads in the system to exclude your preferred core I can't see this helping.