c# - Code sample that shows casting to uint is more efficient than range check -
so looking @ this question , general consensus uint cast version more efficient range check 0. since code in ms's implementation of list assume real optimization. have failed produce code sample results in better performance uint version. have tried different tests , there missing or other part of code dwarfing time checks. last attempt looks this:
class testtype { public testtype(int size) { maxsize = size; random rand = new random(100); (int = 0; < maxiterations; i++) { indexes[i] = rand.next(0, maxsize); } } public const int maxiterations = 10000000; private int maxsize; private int[] indexes = new int[maxiterations]; public void test() { var timer = new stopwatch(); int inrange = 0; int outofrange = 0; timer.start(); (int = 0; < maxiterations; i++) { int x = indexes[i]; if (x < 0 || x > maxsize) { throw new exception(); } inrange += indexes[x]; } timer.stop(); console.writeline("comparision 1: " + inrange + "/" + outofrange + ", elapsed: " + timer.elapsedmilliseconds + "ms"); inrange = 0; outofrange = 0; timer.reset(); timer.start(); (int = 0; < maxiterations; i++) { int x = indexes[i]; if ((uint)x > (uint)maxsize) { throw new exception(); } inrange += indexes[x]; } timer.stop(); console.writeline("comparision 2: " + inrange + "/" + outofrange + ", elapsed: " + timer.elapsedmilliseconds + "ms"); } } class program { static void main() { testtype t = new testtype(testtype.maxiterations); t.test(); testtype t2 = new testtype(testtype.maxiterations); t2.test(); testtype t3 = new testtype(testtype.maxiterations); t3.test(); } } the code bit of mess because tried many things make uint check perform faster moving compared variable field of class, generating random index access , on in every case result seems same both versions. change applicable on modern x86 processors , can demonstrate somehow?
note not asking fix sample or explain wrong it. want see case optimization work.
i suggest attempting code not throw exception when index out of range. exceptions incredibly expensive , can throw off bench results.
the code below timed-average bench 1,000 iterations of 1,000,000 results.
using system; using system.diagnostics; namespace benchtest { class program { const int loopcount = 1000000; const int averagecount = 1000; static void main(string[] args) { console.writeline("starting benchmark"); runtest(); console.writeline("finished benchmark"); console.write("press key exit..."); console.readkey(); } static void runtest() { int cursorrow = console.cursortop; int cursorcol = console.cursorleft; long totaltime1 = 0; long totaltime2 = 0; long invalidoperationcount1 = 0; long invalidoperationcount2 = 0; (int = 0; < averagecount; i++) { console.setcursorposition(cursorcol, cursorrow); console.writeline("running iteration: {0}/{1}", + 1, averagecount); int[] indexargs = randomfill(loopcount, int.minvalue, int.maxvalue); int[] sizeargs = randomfill(loopcount, 0, int.maxvalue); totaltime1 += runloop(testmethod1, indexargs, sizeargs, ref invalidoperationcount1); totaltime2 += runloop(testmethod2, indexargs, sizeargs, ref invalidoperationcount2); } printresult("test 1", timespan.fromticks(totaltime1 / averagecount), invalidoperationcount1); printresult("test 2", timespan.fromticks(totaltime2 / averagecount), invalidoperationcount2); } static void printresult(string testname, timespan averagetime, long invalidoperationcount) { console.writeline(testname); console.writeline(" average time: {0}", averagetime); console.writeline(" invalid operations: {0} ({1})", invalidoperationcount, (invalidoperationcount / (double)(averagecount * loopcount)).tostring("p3")); } static long runloop(func<int, int, int> testmethod, int[] indexargs, int[] sizeargs, ref long invalidoperationcount) { stopwatch sw = new stopwatch(); console.write("running {0} sub-iterations", loopcount); sw.start(); long starttickcount = sw.elapsedticks; (int = 0; < loopcount; i++) { invalidoperationcount += testmethod(indexargs[i], sizeargs[i]); } sw.stop(); long stoptickcount = sw.elapsedticks; long elapsedtickcount = stoptickcount - starttickcount; console.writeline(" - time taken: {0}", new timespan(elapsedtickcount)); return elapsedtickcount; } static int[] randomfill(int size, int minvalue, int maxvalue) { int[] randomarray = new int[size]; random rng = new random(); (int = 0; < size; i++) { randomarray[i] = rng.next(minvalue, maxvalue); } return randomarray; } static int testmethod1(int index, int size) { return (index < 0 || index >= size) ? 1 : 0; } static int testmethod2(int index, int size) { return ((uint)(index) >= (uint)(size)) ? 1 : 0; } } }
Comments
Post a Comment