Carl Love

Carl Love

28070 Reputation

25 Badges

13 years, 34 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are replies submitted by Carl Love

@Kitonum 

piecewise uses assumptions when evaluating conditions with parameters; `if` doesn't. So, if n isn't manifestly an integer, then the n::odd in the `if` evaluates to false, regardless of assumptions. There is a distinction between types (which are checked with type) and properties (which are checked with is). Many types have the same name as an equivalent property; odd, even, and integer are examples of this. The `::` operator can be used to do a type check or a property check. Which is used depends on the context. piecewise is an is context; `if` is a type context.

The expression piecewise(cond, a, b) is almost equivalent to

(()-> `if`(is(cond)::truefalse, `if`(is(cond), a, b), 'procname'()))()

In other words, is forces a decision to true, false, or FAIL; piecewise just remains unevaluated rather than going to FAIL when the condition can't be decided under the current assumptions.

I say almost equivalent because the call to is from piecewise is moderated through a call to the undocumented procedure PiecewiseTools:-Is, and I don't know the exact details of that. In particular, there are many common circumstances where is(cond) evaluates false, but the piecewise remains unevaluated rather than simplifying to b. The code of PiecewiseTools:-Is is fairly easy to read, easier than the code of is.

@tomleslie 

Yes, I agree that the length check for the purposes of showing the excessive-length message should take into account whether the output is already elided. But that's not the way that it's implemented.

Also, the excessive-length message should include "This is not an error. The result has been computed."

@tomleslie 

Give the command

interface(verboseproc= 3);

Then the procedure definitions returned by dsolve won't be elided. Now compare the output of the following two dsolve commands, and you'll see why the length increases:

sol1:= dsolve(dsys3, numeric, initmesh= 8);
sol2:= dsolve(dsys3, numeric, initmesh= 16);

The OP hasn't provided a reason for such an unusually large value of initmesh, and I doubt that there is any good reason. Inceasing maxmesh to a large value often makes sense. I'd only increase initmesh if the problem seems to have trouble "getting started" (as indicated by an error message), and then I'd only increase it gradually.

@roman_pearce 

This is all-the-more reason why one should be able to set kernelopts(numcpus) before a call to Threads. The current situation---where one can only effectively set it immediately after a restart---is unacceptable.

If I simply change my test list to a million Maple floats rather than 32 million integers, then using any number of threads greater than one leads to a substantial increase in real time! It's about 5 times higher when using two threads and nearly 2 times higher when using eight threads. To run this test, simply change the command the creates the input data to

L:= evalf(RandomTools:-Generate(list(integer, 2^20))):

In another test, I tried to defeat the caching by adding elements in a random order. I changed the input to

L:= evalf(RandomTools:-Generate(list(integer, 2^20))):
J:= RandomTools:-Generate(list(integer(range= 1..2^20), 2^20)):
save L, J, "ThreadsTestData.m":

And I changed the test execution (both places!) to

Threads:-Add(L[k], k= J)

@roman_pearce Thank you for the detailed and very useful information, and thank you for running my test on other CPUs. I think that you've mostly explained the phenomena that I observed. So I should probably ignore CPU times for parallel processes on my CPU. Still, the real-time reduction going from four to eight threads on my CPU is very small.

Something else to consider is the sharing of the caches between threads on the same core.

@roman_pearce 

Intel Core i7-3620QM @ 2.4 GHZ running Windows 8.1 64-bit. Intel's website claims that it has four "cores" and eight "threads".

Please let me know if you can achieve substantially different results on any processor.

@Christopher2222 

Thank you for your comment and your interest in the post.

You wrote:

based on performance gains it's hardly worth devoting more than 4 of 5 cpu's to a task, unless for some reason a deadline looms and calculations are required to be completed before a specific time.

Yes, that was my conclusion exactly. I wonder to what extent this is a hardware issue. Perhaps hyperthreading two threads per core is not effective, which is why my "sweet spot" is at four threads---my number of cores.

I wonder if two dual core processors (two physical processors with two independent cores each) would outperform a quad core processor (single processor with four independent cores).

Yes, I'd like to know that. Hopefully my worksheet can be run on as many different processor arrangements as possible. And let's not ignore the possible role that the operating system may have. Please, would some Linux or Mac user run my worksheet?

@sand15 This discussion prompted me to make precise timing measurements using different numbers of cores and analyze the results. It took me several days because there was a big hurdle trying to figure out how to adjust the number of cores when using the Threads package. This was covered in my Question "How to limit the number of processors used by Threads?" The result was that the test needed to be run in a different session for each number of cores, which complicated the programming. But, it's done, and the results are now posted as "Diminishing Returns from Parallel Processing: Is it worth using more than four processors with Threads?" My conclusion was no, but perhaps this is a hardware issue. I need to see results from a machine capable of 16 or more threads.

@Milos Bilik You may be thinking of a continuous Markov chain as being "really hard to compute." This is a discrete Markov chain---I was taught how to do the computations by hand in high school.

I'm not totally convinced that this model is the best for your situation. But, it's trivial to compute, so at the very least it's a good start.

By reading the data with Maple, it would be trivial to compute, empirically, the following conditional probabilities: Let P[i,j] be the probability that j consultations are performed the next business day given that i consultations are performed today. Then P is the transition matrix of a Markov chain.

@acer Here is a simpler test:

nops({Threads:-Seq(Threads:-Self(), k= 1..2^19)});

with the expected result being a positive integer less than or equal to kernelopts(numcpus).

I can confirm what you said: that if the kernelopts(numcpus= ...is issued immediately after restart, then it takes effect.

So, no reader has an idea how to limit the number of processors or what kernelopts(numcpus= ...is supposed to do? I guess that I'll call it a bug and submit an SCR. There's an unusual thing about this bug though. Usually a bug occurs for some inputs to a command or under some circumstances. In this case, it seems like kernelopts(numcpus= ...) doesn't work for any input under any circumstances (on my computer). Could someone running Linux or MacIntosh confirm the results of the worksheet in my Question above?

@sand15 In French, what do you call the relationship between cos(x) and sec(x)? In English, they're called reciprocal functions.

@acer Ah, if I'd known that RGB24ToName had an option palette, I wouldn't have written my RGBtoName. That's an example of what I meant by "The APIs are inconsistent."

@adel-00 Now that the implicitplot is done, we know ranges for the two positive roots. One is between 0 and 1, and the other is between 8 and 10. Once that is known, it's easier to use fsolve to get the roots.

r1:= (So::And(numeric, satisfies(x-> x >= 4 and x <= 5)))->
     fsolve(eval(Q, so= So), s= 0..1)
:
r2:= (So::And(numeric, satisfies(x-> x >= 4 and x <= 5)))->
     fsolve(eval(Q, so= So), s= 8..10)
:
xs:= (u,so)-> (so-u)*d*(a1+u)/(m1*u):
zs:= xs-> ((m2-d2)*xs-a2*d2)*(a3+ys)/(m3*(a2+xs)):
Xs1:= so-> xs(r1(so),so):
Xs2:= so-> xs(r2(so),so):
plot([Xs||(1..2)], 4..5);
Zs1:= so-> zs(Xs1(so)):
Zs2:= so-> zs(Xs2(so)):
plot([Zs||(1..2)], 4..5);

First 401 402 403 404 405 406 407 Last Page 403 of 709