Table of Contents

Fusion — np.evaluate vs unfused chains (and NumPy context)

np.evaluate runs a whole expression tree in one NDIter pass (no intermediates). Fixed-expression gate plus an operand-layout sweep of the flagship a*b+c (C/F/T/strided/bcast — does the fused single-pass win survive non-contiguous operands?), not a dtype/layout matrix — so reported as-is.

NumSharp — fused np.evaluate vs unfused np.* chains (4M elements, best-of-9; (Nx) = unfused ÷ fused, >1 = fusion faster):

correctness cross-checks ok

4M float64, best window (min over ~200 ms):
  a*b+c       fused    3.42 ms   unfused    5.68 ms   (1.66x)
  (a-b)/(a+b) fused    2.83 ms   unfused   11.66 ms   (4.12x)
  sum(a*b)    fused    2.17 ms   unfused    3.67 ms   (1.69x)
  sum(af*bf)  fused    1.22 ms   unfused    1.64 ms   (1.34x)  [f32]
  a*b+c out=  fused    3.33 ms   [1-pass fused-into-out]
  i4*2+f8     fused    2.73 ms   unfused    3.91 ms   (1.43x)

  a*b+c across operand layouts (2-D 2000x2000, all 3 operands same layout):
    [C      ] fused    3.44 ms   unfused    5.90 ms   (1.72x)
    [F      ] fused   11.76 ms   unfused   17.82 ms   (1.52x)
    [T      ] fused   11.82 ms   unfused   17.38 ms   (1.47x)
    [strided] fused   11.84 ms   unfused   16.55 ms   (1.40x)
    [bcast  ] fused    2.23 ms   unfused    9.12 ms   (4.10x)

NumPy — absolutes on the same box (context for the unfused column):

numpy 2.4.2, 4M float64, best window (min over ~200 ms):
  a*b+c         12.68 ms
  (a-b)/(a+b)   19.13 ms
  sum(a*b)       8.42 ms
  sum(af*bf)     4.23 ms  [f32]
  a*b+c out=     5.08 ms  [two-pass with out=]
  i4*2+f8        9.93 ms
  a*b+c across operand layouts (2-D 2000x2000, unfused):
    [C      ]   12.83 ms
    [F      ]   12.50 ms
    [T      ]   12.59 ms
    [strided]    7.87 ms
    [bcast  ]   12.19 ms