Cancelling a Task is throwing an exception

后端 未结 5 2070
[愿得一人]
[愿得一人] 2020-11-27 03:52

From what I\'ve read about Tasks, the following code should cancel the currently executing task without throwing an exception. I was under the impression that the whole poin

5条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-27 04:31

    Some of the above answers read as if ThrowIfCancellationRequested() would be an option. It is not in this case, because you won't get your resulting last prime. The idiomatic way that "the method you called was cancelled" is defined for cases when canceling means throwing away any (intermediate) results. If your definition of cancelling is "stop computation and return the last intermediate result" you already left that way.

    Discussing the benefits especially in terms of runtime is also quite misleading: The implemented algorithm sucks at runtime. Even a highly optimized cancellation will not do any good.

    The easiest optimization would be to unroll this loop and skip some unneccessary cycles:

    for(i=2; i <= num/2; i++) { 
      if((num % i) == 0) { 
        // num is evenly divisible -- not prime 
        isprime = false; 
        factor = i; 
      }
    } 
    

    You can

    • save (num/2)-1 cycles for every even number, which is slightly less than 50% overall (unrolling),
    • save (num/2)-square_root_of(num) cycles for every prime (choose bound according to math of smallest prime factor),
    • save at least that much for every non-prime, expect much more savings, e.g. num = 999 finishes with 1 cycle instead of 499 (break, if answer is found) and
    • save another 50% of cycles, which is of course 25% overall (choose step according to math of primes, unrolling handles the special case 2).

    That accounts to saving a guaranteed minimum of 75% (rough estimation: 90%) of cycles in the inner loop, just by replacing it with:

    if ((num % 2) == 0) {
      isprime = false; 
      factor = 2;
    } else {
      for(i=3; i <= (int)Math.sqrt(num); i+=2) { 
        if((num % i) == 0) { 
          // num is evenly divisible -- not prime 
          isprime = false; 
          factor = i;
          break;
        }
      }
    } 
    

    There are much faster algorithms (which I won't discuss because I'm far enough off-topic) but this optimization is quite easy and still proves my point: Don't worry about micro-optimizing runtime when your algorithm is this far from optimal.

提交回复
热议问题