How to Call a R Statistics Function to Optimize C# Function

Method optimization

The Smooth method can be simplified (or in your term: optimized?) in some ways:

  1. To remove the conditional (if-else) nested blocks, consider the use of early return for conditions which are simpler among the two or has no further continuation. This way, you may remove "difficult-to-read" nested blocks.
  2. To avoid "duplicate" blocks, blocks with identical actions should be considered to be grouped together rather than being separated.
  3. Think if reversing the condition can help to simplify your code
  4. Exploit whatever beneficial behaviors that you know about the language evaluation. For instance, for C#, in the argument of the conditional statement like if (a || b) case, the left expression (that is: a) will be evaluated first - this is known as Short Circuit Evaluation.
  5. Whenever possible, and without significantly losing the readability, consider of using Ternary operator to replace if-else block.
  6. Declare variable that you will be using multiple times without changing the value only once
  7. Watch out for overlapping (doubled/duplicated) conditions!
  8. Use correct data type will help!

For your case, the simplified code can be something like this

uint rounds = 0; //read 8.
void Smooth(ref int botChips, ref bool botTurn, Label botStatus, int name, int n, int r) {
Random rand = new Random();
int rnd = rand.Next(1, 3);
if (rounds <= 1) { //read 8.
if (call <= 0) {
Check(ref botTurn, botStatus); //since your Check doesn't change rounds, this is legal
return; //read 1. early return
} //beyond this call > 0
if (call >= RoundN(botChips, n) || botChips < call * 2) { //read 2., 3., 4., and 7.
Call(ref botChips, ref botTurn, botStatus);
return; //read 1.
} //beyond this is the opposite of both conditions
Raise *= 2;
Raised(ref botChips, ref botTurn, botStatus);
}

if (rounds == 2 || rounds == 3) {
if (call <= 0) {
if (rnd == 1) { //call <= 0, rnd == 1, similar to the block on call < rNBChips, may potentially be further simplified
Raise = RoundN(botChips, r);
Raised(ref botChips, ref botTurn, botStatus);
} else if (rounds == 2) //read 7. rnd is definitely not 1, no need for further check
Check(ref botTurn, botStatus);
return; //read 1. this is valid since you don't want to continue
}
double rNBChips = RoundN(botChips, r); //read 6. this way you avoid multiple calls. It both shorter and faster
if (call < rNBChips) { //read 3.
Raise = Raise <= rNBChips / 2 ? rNBChips : Raise * 2; //read 5.
Raised(ref botChips, ref botTurn, botStatus);
return; // read 1.
}
if (botChips > call) {
Call(ref botChips, ref botTurn, botStatus);
return; //read 1.
}
raising = false;
botTurn = false;
botChips = 0;
botStatus.Text = "Call " + call;
tbPot.Text = (int.Parse(tbPot.Text) + call).ToString();
}
}

Without the comments it even looks a lot more compact, like this

uint rounds = 0;
void Smooth(ref int botChips, ref bool botTurn, Label botStatus, int name, int n, int r) {
Random rand = new Random();
int rnd = rand.Next(1, 3);
if (rounds <= 1) {
if (call <= 0) {
Check(ref botTurn, botStatus);
return;
}
if (call >= RoundN(botChips, n) || botChips < call * 2) {
Call(ref botChips, ref botTurn, botStatus);
return;
}
Raise *= 2;
Raised(ref botChips, ref botTurn, botStatus);
}

if (rounds == 2 || rounds == 3) {
if (call <= 0) {
if (rnd == 1) {
Raise = RoundN(botChips, r);
Raised(ref botChips, ref botTurn, botStatus);
} else if (rounds == 2)
Check(ref botTurn, botStatus);
return;
}
double rNBChips = RoundN(botChips, r);
if (call < rNBChips) {
Raise = Raise <= rNBChips / 2 ? rNBChips : Raise * 2;
Raised(ref botChips, ref botTurn, botStatus);
return;
}
if (botChips > call) {
Call(ref botChips, ref botTurn, botStatus);
return;
}
raising = false;
botTurn = false;
botChips = 0;
botStatus.Text = "Call " + call;
tbPot.Text = (int.Parse(tbPot.Text) + call).ToString();
}
}

Compiler optimization of repeated accessor calls

From what I know, the C# compiler doesn't optimize this, because it can't be certain of side-effects (e.g. what if you have accessCount++ in the getter?) Take a look here at an excellent answer by Eric Lippert

From that answer:

The C# compiler never ever does this sort of optimization; as noted, doing so would require that the compiler peer into the code being called and verify that the result it computes does not change over the lifetime of the callee's code. The C# compiler does not do so.

The JIT compiler might. No reason why it couldn't. It has all the code sitting right there. It is completely free to inline the property getter, and if the jitter determines that the inlined property getter returns a value that can be cached in a register and re-used, then it is free to do so. (If you don't want it to do so because the value could be modified on another thread then you already have a race condition bug; fix the bug before you worry about performance.)

Just a note, seeing as Eric's on the C# compiler team, I trust his answer :)

is there a way to call R functions from C# and retrieve the result in C#

Given there is a COM interface to R, you can use C#'s COM interop to control it.

See this article for more details: http://www.codeproject.com/KB/cs/RtoCSharp.aspx

Can the C# compiler or JIT optimize away a method call in a lambda expression?

Well, it's a bit of a complex answer.

There are two things involved here. (1) the compiler and (2) the JIT.

The compiler

Simply put, the compiler just translates your C# code to IL code. It's a pretty trivial translation for most cases and one of the core ideas of .NET is that each function is compiled as an autonomous block of IL code.

So, don't expect too much from the C# -> IL compiler.

The JIT

That's... a bit more complicated.

The JIT compiler basically translates your IL code to assembler. The JIT compiler also contains an SSA based optimizer. However, there's a time limit, because we don't want to wait too long before our code starts to run. Basically this means that the JIT compiler doesn't do all the super cool stuff that will make your code go extremely fast, simply because that would cost too much time.

We can of course just put it to the test :) Ensure VS will optimize when you run (options -> debugger -> uncheck suppress [...] and just my code), compile in x64 release mode, put a breakpoint and see what happens when you switch to assembler view.

But hey, what's the fun in only having theory; let's put it to the test. :)

static bool Foo(Func<int, int, int> foo, int a, int b)
{
return foo(a, b) > 0; // put breakpoint on this line.
}

public static void Test()
{
int n = 2;
int m = 2;
if (Foo((a, b) => a + b, n, m))
{
Console.WriteLine("yeah");
}
}

First thing you should notice is that the breakpoint is hit. This already tells that the method ain't inlined; if it were, you wouldn't hit the breakpoint at all.

Next, if you watch the assembler output, you'll notice a 'call' instructions using an address. Here's your function. On closer inspection, you'll notice that it's calling the delegate.

Now, basically this means that the call is not inlined, and therefore is not optimized to match the local (method) context. In other words, not using delegates and putting stuff in your method is probably faster than using delegates.

On the other hand, the call is pretty efficient. Basically the function pointer is simply passed and called. There's no vtable lookup, just a simple call. This means it probably beats calling a member (e.g. IL callvirt). Still, static calls (IL call) should be even faster, since these are predictable compile-time. Again, let's test, shall we?

public static void Test()
{
ISummer summer = new Summer();
Stopwatch sw = Stopwatch.StartNew();
int n = 0;
for (int i = 0; i < 1000000000; ++i)
{
n = summer.Sum(n, i);
}
Console.WriteLine("Vtable call took {0} ms, result = {1}", sw.ElapsedMilliseconds, n);

Summer summer2 = new Summer();
sw = Stopwatch.StartNew();
n = 0;
for (int i = 0; i < 1000000000; ++i)
{
n = summer.Sum(n, i);
}
Console.WriteLine("Non-vtable call took {0} ms, result = {1}", sw.ElapsedMilliseconds, n);

Func<int, int, int> sumdel = (a, b) => a + b;
sw = Stopwatch.StartNew();
n = 0;
for (int i = 0; i < 1000000000; ++i)
{
n = sumdel(n, i);
}
Console.WriteLine("Delegate call took {0} ms, result = {1}", sw.ElapsedMilliseconds, n);

sw = Stopwatch.StartNew();
n = 0;
for (int i = 0; i < 1000000000; ++i)
{
n = Sum(n, i);
}
Console.WriteLine("Static call took {0} ms, result = {1}", sw.ElapsedMilliseconds, n);
}

Results:

Vtable call took 2714 ms, result = -1243309312
Non-vtable call took 2558 ms, result = -1243309312
Delegate call took 1904 ms, result = -1243309312
Static call took 324 ms, result = -1243309312

The thing here that's interesting is actually the latest test result. Remember that static calls (IL call) are completely deterministic. That means it's a relatively simple thing to optimize for the compiler. If you inspect the assembler output, you'll find that the call to Sum is actually inlined. This makes sense. Actually, if you would test it, just putting the code in the method is just as fast as the static call.

A small remark about Equals

If you measure performance of hash tables, something seems fishy with my explanation. It appears as-if IEquatable<T> makes things go faster.

Well, that's actually true. :-) Hash containers use IEquatable<T> to call Equals. Now, as we all know, objects all implement Equals(object o). So, the containers can either call Equals(object) or Equals(T). The performance of the call itself is the same.

However, if you also implement IEquatable<T>, the implementation usually looks like this:

bool Equals(object o)
{
var obj = o as MyType;
return obj != null && this.Equals(obj);
}

Furthermore, if MyType is a struct, the runtime also needs to apply boxing and unboxing. If it would just call IEquatable<T>, none of these steps would be necessary. So, even though it appears slower, this has nothing to do with the call itself.

Your questions

Will there be any (performance) advantage of moving the evaluation of ListOfDates.Max() out of the Where clause in this case, or will 1. the compiler or 2. JIT optimize this away?

Yes, there will be an advantage. The compiler / JIT won't optimize it away.

I believe C# will only do constant folding at compile time, and it could be argued that ListOfDates.Max() can not be known at compile time unless ListOfDates itself is somehow constant.

Actually, if you change the static call to n = 2 + Sum(n, 2) you'll notice that the assembler output will contain a 4. Which proves that the JIT optimizer does do constant folding. (Which is quite obvious actually if you know about how SSA optimizers work... const folding and simplification are called a few times).

The function pointer itself isn't optimized. It might be in the future though.

Perhaps there is another compiler (or JIT) optimization that makes sure that this is only evaluated once?

As for 'another compiler', if you're willing to add 'another language', you can use C++. In C++ these kinds of calls are sometimes optimized away.

More interestingly, Clang is based on LLVM, and there are a few C# compilers for LLVM as well. I believe Mono has an option to optimize to LLVM, and CoreCLR was working on LLILC. While I haven't tested this, LLVM can definitely do these kinds of optimizations.

How to call function depending on the datatype of the variable the result is assigned to

Return type issues aside. You can not do this the function declarations collide. The compiler needs a unique signature for each method it compiles. It generates those signatures using the function name and the parameters. It does not care about return types.

Call Method based on Type of Parameter

Based on the information you've provided so far, your question appears to be a duplicate of How to call a function dynamically based on an object type. I agree with the answer, that the fact that you want to do this suggests you should rethink the design. But, you can use dynamic to accomplish what you want.

Here's a simple console program that demonstrates the basic idea:

class Program
{
static void Main(string[] args)
{
A b = new B(), c = new C();

M(b);
M(c);
}

static void M(A a)
{
WriteLine("M(A)");
M((dynamic)a);
}

static void M(B b)
{
WriteLine("M(B)");
}

static void M(C c)
{
WriteLine("M(C)");
}
}

class A { }
class B : A { }
class C : A { }

The output is:

M(A)
M(B)
M(A)
M(C)

As you can see, in each case the M(A) method is called first, and then the appropriate M(B) or M(C) overload is called from M(A).

In your own example, this could look something like this:

public static DoThings
{
public static void HandleRequest(Request r)
{
// Dynamic dispatch to actual method:
HandleRequest((dynamic)r);
}

public static void HandleRequest(AudioRequest r)
{
// Do things.
}

public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}

Note that dynamic does incur a run-time cost, particularly the first time a method is called with a given run-time type. But depending on the frequency and complexity of these "requests", using dynamic could be the cleanest way out of the current situation.



Related Topics



Leave a reply



Submit