Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

There is something that has been troubling me for a while. At least in version 7, the performance of a / b and a - b is not equivalent to, and significantly inferior to, Divide[a, b] and Subtract[a, b], despite the fact that these are treated as equivalent in the documentation. As a terse code fanatic it chafes me to have to write out the longer forms, but that is only the beginning of my concern, because the latter, faster forms are transparently converted into the former, slower forms.

Examples from the documentation for Divide:

x/y or Divide[x,y] is equivalent to x y^-1.

Divide[x,y] can be entered in StandardForm and InputForm as x ÷ y, x EscdivEsc y or x \[Divide] y.

Proof that these statements are false:

{a, b} = List @@ RandomReal[{-50, 50}, {2, 1*^7}];

Do[a/b, {50}]          // Timing // First
Do[a b^-1, {50}]       // Timing // First
Do[a\[Divide]b, {50}]  // Timing // First
Do[Divide[a, b], {50}] // Timing // First
2.262

2.231

2.184

0.437

Divide[a, b] is not evaluated in the same manner as the rest. Similarly for subtraction:

Do[a - b, {50}]          // Timing // First
Do[a + (-1 b), {50}]       // Timing // First
Do[Subtract[a, b], {50}] // Timing // First
3.651

3.65

1.404

Although the examples above use packed arrays (see Why does list assignment with a packed array result in unpacked values? for an explanation of List @@) the same performance differential exists with unpacked lists.

One can see with Trace that the short forms induce additional operations:

a = Range[1, 2];
b = Range[3, 4];

a/b          // Trace
Divide[a, b] // Trace
{{a,{1,2}}, {{b,{3,4}}, 1/{3,4}, {1/3,1/4}}, {1,2} {1/3,1/4}, {1/3,1/4} {1,2}, 1/3,1/2}}

{{a,{1,2}}, {b,{3,4}}, {1,2}/{3,4}, {1/3,1/2}}
a - b          // Trace
Subtract[a, b] // Trace
{{a,{1,2}}, {{b,{3,4}}, -{3,4}, {-3,-4}}, {1,2} + {-3,-4}, {-3,-4} + {1,2}, {-2,-2}}

{{a,{1,2}}, {b,{3,4}}, {1,2} - {3,4}, {-2,-2}}

Note the false equivalence in this output; the fast Divide and Subtract operations are formatted as {1,2}/{3,4} and {1,2} - {3,4}, yet these slow forms are not part of their evaluation process.

More problematic is when this false equivalence changes evaluation. For example, if you try to work symbolically with Subtract and Divide in an evaluated expression and use the result these faster forms are replaced with the slower ones:

expr = Divide[x, y] + Subtract[x, y];
fn = Function[{x, y}, Evaluate @ expr]
fn // FullForm
Function[{x, y}, x + x/y - y]

Function[List[x,y], Plus[x, Times[x, Power[y,-1]], Times[-1,y]]]

Note also that Divide and Subtract are stripped when converting forms in the Front End (menu Cell > Convert To) so even without evaluation these operators may be lost.

Therefore I have these questions:

  • Why are these operations universally treated as equivalent when they are clearly not programmatically equivalent?

  • Why does Mathematica not include optimization for cases of numeric division and subtraction to eliminate the additional evaluation steps?

  • Is there a practical way to add global optimizations to automatically convert these operations to the fast forms before numeric evaluation?

  • Failing the above, what is the best way to work symbolically with actual division and subtraction operators for the sake of performance?

  • Is internally representing division and subtraction as multiplication and addition really the only mathematically valid design option? Couldn't these instead be first-class operators that are recognized as equivalent to Times and Plus for the purpose of pattern matching but not converted into Times and Plus (which introduces additional Times and Power operations)?

share|improve this question
9  
Related question: mathematica.stackexchange.com/questions/39200/… –  Mark Adler Jan 22 at 17:46
1  
Something about the timing is interesting. On my PC which runs at 3.8 GHz (base is 3.2 GHz, Intel i7-3930K, MMA V. 9.0.1), The short form timing for subtraction is 4.59375 seconds whereas the long form is an astonishing 0.125 seconds (an order of magnitude faster than yours). –  RunnyKine Jan 22 at 18:07
2  
@Peltio To whom are you speaking? I am fairly certain this is not a superficial difference as I attempted to show with Trace. –  Mr.Wizard Jan 22 at 18:41
1  
Something funny is going on. The results for power are all slower than the Divide. Do[a*b, {50}] // Timing // First Do[Times[a, b], {50}] // Timing // First Do[a b, {50}] // Timing // First. Also, while running this, more than one core is used. –  Ajasja Jan 22 at 20:18
1  
Running on a somewhat elderly 8 core intel xeon machine (win7 / M9.0.1). I see two oddities. The a/b variant uses ~10Mb more memory at peak than the Divide[a,b] case. The a/b variant also engages only ~40% of the machine's aggregate compute capacity (in task manager). The Divide[a, b] peaks at 66%. This suggests something down in the library calls made. Would be interesting to see the same under linux. –  Ymareth Jan 22 at 21:28

2 Answers 2

An extended comment. I'm not sure if this has been realized, please correct me if it has. The result of the Divide[a,b] operation is not the same as the first 3 which are identical.

{a, b} = List @@ RandomReal[{-50, 50}, {2, 1*^7}];

x1 = a/b;
x2 = a b^-1;
x3 = a/b;
x4 = Divide[a, b];

Now...

Tally[x1 - x2]
Tally[x2 - x3]

Both give 10^7 zeros.

Tally[x3 - x4]

Gives ~ 7,500,000 zeros and 2,500,000 slight differences.

share|improve this answer
1  
x4 is also what I get from using the apache commons math library (3.2) ebeDivide method on RealVectors made from a and b using JLink and loading the results back to Mathematica. So Divide[a,b] in Mathematica == a / b in Java. –  Ymareth Apr 4 at 12:10
    
This has been observed, and it was discussed in (39200) and on MathGroup as linked by Daniel in the first comment below that question. Nevertheless it's an observation I failed to include in my question. –  Mr.Wizard Apr 4 at 19:07

There is no possible known method to add subtract multiply or divide, using a microprocessor, with equal efficiency. If you look at the various hardware implementations of ALU implementations you will see radically different designs for each function that all have pros and cons. It's an open question in computer science that will make you a very rich person if you could design a circuit that could do all four primary functions efficiently and equally efficient.

share|improve this answer
2  
This does not in any way answer the question. –  Simon Woods Mar 21 at 19:16
    
Sorry Simon, I thought it was clear that there is no answer. In no way can MM do math operations with equal efficiency if the hardware can't do it. –  Sinistar Mar 22 at 3:28
2  
I didn't ask for "equal efficiency" -- I simply asked for the better performance that I clearly demonstrated Mathematica itself is capable of, using a specific input syntax. Sorry, but -1 from me. :-( –  Mr.Wizard Mar 22 at 11:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.