Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I had a go at this and am getting some results that are good, too good :(( Something is wrong somewhere, but I don't see it. I am not getting runtimes in the order of hours, even for n from 1 to 10,000,000, (ten million):</p> <pre><code>8 tests, 8 tasks, counting to 1000000, using 14 threads: Validated: 1000000 in 670ms Validated: 1000000 in 671ms Validated: 1000000 in 624ms Validated: 1000000 in 656ms Validated: 1000000 in 655ms Validated: 1000000 in 655ms Validated: 1000000 in 640ms Validated: 1000000 in 686ms Average time: 657ms Total validated: 8000000 8 tests, 8 tasks, counting to 10000000, using 14 threads: Validated: 10000000 in 8081ms Validated: 10000000 in 7441ms Validated: 10000000 in 7784ms Validated: 10000000 in 7598ms Validated: 10000000 in 7956ms Validated: 10000000 in 7534ms Validated: 10000000 in 7816ms Validated: 10000000 in 7769ms Average time: 7747ms Total validated: 80000000 </code></pre> <p>Note that, although it says 14 threads, that is for the whole pool. One thread is always used up waiting for other tasks to complete, so only 13 threads were actually available to run the validation. For some reason, that was optimum.</p> <p>OK, my i7 is flat-out on all 4/8 cores, but I can't see runtimes of hours shrinking into seconds just because I have more cores and have split off the work to all of them :(</p> <p>This is what I used. It's a bit different to the way you did it 'cos I had most of the tools/code lying around. It's Visual C++, to start with. There are two classes. Each run is managed by a 'PoolTest' class that submits several 'TestTask' instances to a threadpool, one for each segment of the complete range of integers to be validated. You will notice your code copied/pasted into the TestTask class. I highlighted where the TestTask is assembled in the PoolTest code. The 'PoolTest' class then waits on an Event for all the 'TestTask' instances to complete - it can do this because the TestTask's call back to a PoolTest 'taskComplete' method on completion. This method accesses a thread-safe counter that is counted up when TestTasks are submitted and counted down by the 'taskComplete' method.</p> <p>This code I've re-used complicates things a bit because it can repeat the run multiple times to get an average time, so the complete set of TestTasks can be issued mutiple times.</p> <p>When the last ever TestTask counts down to zero, it signals the Event and the PoolTest will then run again signaling completion of the whole test run to the GUI, (not bothered listing GUI stuff 'cos not relevant).</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace WindowsFormsApplication1 { public class TestTask: Task{ public int validated; public int fromVal, toVal; public int ticks; long collatz(long n) { while (n != 1) { if (n % 2 == 0) n = (n / 2); else n = (3 * n + 1); } return (n); } public override void run(){ int index; int localTo = toVal; int localFrom = fromVal; int localVal = 0; for (index = localFrom; index &lt; localTo; index++) { // if not disproved, inc the stack 'validated' if (1 == collatz(index + 1)) localVal++; } validated = localVal; // put stack result into instance field, } public TestTask(int paramx, EventHandler OnDone) : base(paramx, OnDone){} }; /* a task that submits testTask instances. */ public class PoolTest:Task{ int FnumTasks; int FnumTests; int Fcount; int FtestCount; int taskCount; int startTicks; int endTicks; int totalTicks; EventHandler FonTaskComplete; AutoResetEvent testCompleteEvent; public int average; public int testTicks; public int Vone; public int Vtot; public TestTask thisTestTask; public PoolTest(int testsNum, int tasks, int count, EventHandler taskDone, EventHandler testDone) : base(0, testDone) { FnumTests=testsNum; FtestCount=testsNum; FnumTasks=tasks; Fcount=count; Vtot = 0; Vone = 0; totalTicks = 0; FonTaskComplete=taskDone; // call after each test to report ticks testCompleteEvent= new AutoResetEvent(false); } void submitAtest(){ // queue up numTasks testTask instances taskCount=FnumTasks; startTicks = System.Environment.TickCount; //*********************THIS IS WHERE THE RANGES AND TASKS ARE ASSEMBLED int startNum = 0; // here, start at 0 and build up the ranges int countIncrement=Fcount/FnumTasks; // calc. range size int endNum=startNum+countIncrement; // and so init. start/end TestTask newTask; for (int i = 1; i &lt; FnumTasks; i++) // one less than requested { newTask=new TestTask(0, taskComplete); newTask.fromVal=startNum; // load in the start/end for the loop newTask.toVal = endNum; myPool.submit(newTask); // off it goes, see you later startNum = endNum; // now move range up for endNum += countIncrement; // next TestTask } // treat last range separately to cover div rounding when // calculating 'countIncrement' newTask = new TestTask(0, taskComplete); // do last one newTask.fromVal = startNum; newTask.toVal = Fcount; myPool.submit(newTask); // send off the last one } //***************************************************************** public override void run(){ submitAtest(); //start off the first run of testTasks testCompleteEvent.WaitOne(); } void taskComplete(object sender, EventArgs e){ // called when a testTask bool finishedTasks; // instance is complete lock (this) { thisTestTask = (TestTask)sender; taskCount--; // another one down Vone += thisTestTask.validated; // Vone - total for one run Vtot += thisTestTask.validated; // total for all runs finishedTasks = (taskCount == 0); // this run all done yet? if (finishedTasks) { endTicks = System.Environment.TickCount; // yes, so calc. elapsed time testTicks=endTicks-startTicks; thisTestTask.ticks = testTicks; totalTicks=totalTicks+testTicks; if (0!=--FtestCount) { // done all the test runs? thisTestTask.validated = Vone; // use this field to return run total FonTaskComplete(thisTestTask, null); // and signal result of test Vone = 0; submitAtest(); // no, so send off another load } else{ average=totalTicks/FnumTests; // done all test runs! testCompleteEvent.Set(); // signal all runs completed }; } } } }; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload