Joe Riel

9660 Reputation

23 Badges

20 years, 16 days

MaplePrimes Activity


These are replies submitted by Joe Riel

You might have a look at www.mapleprimes.com/forum/magicsquare

You might have a look at www.mapleprimes.com/forum/magicsquare

That certainly is a significant factor.  For example (increasing the base to 10^6),

task := proc(i, j)
local k;
    if j - i < 10^6 then
        return add(k, k = i .. j);
    else
        k := iquo(i+j,2);
        Threads:-Task:-Continue(`+`
                                , 'Tasks' = [task, [i, k], [k+1,j]]
                               )
    end if;
end proc:

n := 10^8:
time[real](Threads:-Task:-Start( task, 1, n ));  2.169

Note, however, that the nonrecursive approach does reasonably well even with a base of 1000

AddThreaded2 := proc(n::nonnegint, K::posint)
local r,i;
    r := irem(n,K);
    Threads:-Task:-Continue(`+`
                            , 'Tasks' = [addrng
                                         , seq([i..i+K-1], i=1..n-K+1,K)
                                         , `if`(r = 0
                                                , NULL
                                                , [n-r+1..n]
                                               )
                                        ]
                           );
end proc:
n := 10^8:
time[real](Threads:-Task:-Start(AddThreaded2, n, 1000));  3.514

However, if called with a base (K) of 100, we run into stacklimit issues.

Here's a simple example where things go wrong.  It is taken from ?Threads[Task][Start] (slightly modified, but the help page code exhibits the same symptoms):


task := proc(i, j)
local k;
    if j - i < 1000 then
        return add(k, k = i .. j);
    else
        k := iquo(i+j,2);
        Threads:-Task:-Continue(`+`
                                , 'Task' = [task, i, k]
                                , 'Task' = [task, k + 1, j]
                               )
    end if;
end proc:

n := 10^8:
time[real](Threads:-Task:-Start( task, 1, n ));
                                                                     10.703

The allocated memory is nearly 800MB.  Contrast this with

restart;
n := 10^8:
time[real](add(k, k=1..n));
                                                                       7.364

 

If we avoid the recursion and just split the range into a given number of threads we do much better

addrng := proc(rng)
local k;
    add(k, k=rng)
end proc:

AddThreaded := proc(n::nonnegint, m::posint)
local p,i;
    p := iquo(n,m);
    Threads:-Task:-Continue(`+`
                            , 'Tasks' = [addrng
                                         , seq([p*i+1..p*(i+1)], i=0..m-2)
                                         , [p*(m-1)+1..n]
                                        ]
                           );
end proc:

n := 10^8:
time[real](Threads:-Task:-Start(AddThreaded, n, 1));    7.116
time[real](Threads:-Task:-Start(AddThreaded, n, 2));    3.717
time[real](Threads:-Task:-Start(AddThreaded, n, 4));    2.206
time[real](Threads:-Task:-Start(AddThreaded, n, 8));    2.267
time[real](Threads:-Task:-Start(AddThreaded, n, 16));   2.144
time[real](Threads:-Task:-Start(AddThreaded, n, 32));   2.210
time[real](Threads:-Task:-Start(AddThreaded, n, 2^6));  2.185

During the recursive routine (task), only one core at a time ever hits 100% utilization, the other three (on an i5) average much less than 50%. With the nonrecursive routine all four cores are near 100% utilization if m >= 4.

I just noticed that if we use the Tasks options, rather than multiple Task(s), in the recursive routine, there is a noticeable improvement, though it is still no better than the non-threaded call to add:

task := proc(i, j)
local k;
    if j - i < 1000 then
        return add(k, k = i .. j);
    else
        k := iquo(i+j,2);
        Threads:-Task:-Continue(`+`
                                , 'Tasks' = [task, [i, k], [k+1,j]]
                               )
    end if;
end proc:
n := 10^8:
time[real](Threads:-Task:-Start( task, 1, n )); 
                                                               8.420





 

There is a flaw in the timing.  To measure the actual elapsed time, you have to use time[real]().  Using time() returns a longer time in that it gives the total of all the cores cpu times (more or less).  With this example on a 4 core machine using time[real] I get 93 seconds for the 1-thread call and 98 seconds for the 3-thread call.  No improvement, but no significant loss.

I was wondering what the application was.

Note that the matrix structure is deprecated, its replacement constructor is Matrix. You don't need to assign the variables to assign the Matrix, just do

Matrix(4,4, [W(A[])[]])

You can use randomize(); after the restart to reseed the random number generator.

 

I was wondering what the application was.

Note that the matrix structure is deprecated, its replacement constructor is Matrix. You don't need to assign the variables to assign the Matrix, just do

Matrix(4,4, [W(A[])[]])

You can use randomize(); after the restart to reseed the random number generator.

 

Show this integral.  And state the parameters that vary in such a way that permit it to be graphed (in a 3D volume).

My point is that unless you fix one of the ranges, or provide some other constraint, the indefinite integral is an expression in terms of x, y, and z (or whatever three coordinates you choose). You'll have a hard time plotting that.  One generally requires n+1 dimensions to graph an expression of n variables.

Show this integral.  And state the parameters that vary in such a way that permit it to be graphed (in a 3D volume).

My point is that unless you fix one of the ranges, or provide some other constraint, the indefinite integral is an expression in terms of x, y, and z (or whatever three coordinates you choose). You'll have a hard time plotting that.  One generally requires n+1 dimensions to graph an expression of n variables.

Yes, you are correct.  I should have looked.  The package is in Maple 13.

Yes, you are correct.  I should have looked.  The package is in Maple 13.

Are you sure about the path?  /Documents/... is rather strange for a *nix system.  Did you mean /home/yourname/Documents/...

 

Are you sure about the path?  /Documents/... is rather strange for a *nix system.  Did you mean /home/yourname/Documents/...

 

Do you mean the reference I made to using noweb with Maple?  I have not written that up, but will try to.  If nothing else it will give me an excuse to post the knoweb.sty file here, which improves Ramsey's noweb.sty file.

A problem with the puzzle is that it is not well specified and hence readily cooked.  Consider the first part, where the goal is to get as far away as possible before being caught.  The intended solution is to run directly away from the oncoming raptor, however, that isn't necessarily the best strategy (though certainly the most likely).  The raptor has a given maximum acceleration, while your acceleration is implied as infinite.  If we assume that limit on the raptor's acceleration applies in all directions (i.e. the raptor can instantly change the direction of his acceleration vector, but the magnitude of the acceleration must remain below the limit) then it is possible to avoid capture by sidestepping the beast.

To properly define the problem a capture radius needs to be specified.  That is, once the raptor is within that distance of the prey, the prey is considered caught.  To make this tractable, let's assume the raptor's velocity is unlimited.  So we have three parameters: 

  Ar = maximum magnitude of raptor's acceleration vector
  Rr = capture radius
  Vp = maximum magnitude of prey's velocity vector (acceleration, in any direction, is unlimited)

Given that, under what initial conditions (if any) can the prey successfully elude the raptor?

First 108 109 110 111 112 113 114 Last Page 110 of 195