code: def einsum_mulacc(einsum, get_strides, expand):
      def einscripts(x):
          return "".join(["abcdefghijklmnopqrstuvwxyz"[i] for i in x])
  
      def axes_slice(strides):
          return tuple(
              i for i, s in enumerate(strides) if s != 0
          ), tuple(slice(None) if s != 0 else 0 for s in strides)
  
      def mulacc(a, b, new_shape):
          (a_axes, a_slices), (b_axes, b_slices) = axes_slice(
              get_strides(a)
          ), axes_slice(get_strides(b))
          out = [
              i
              for i in range(len(new_shape))
              if a.shape[i] == new_shape[i]
              and (i in a_axes or i in b_axes)
          ]
          ret = einsum(
              f"{einscripts(a_axes)}, {einscripts(b_axes)} -> {einscripts(out)}",
              a[a_slices],
              b[b_slices],
          )
          return expand(
              ret.reshape(
                  tuple(
                      1 if i not in a_axes and i not in b_axes else s
                      for i, s in enumerate(new_shape)
                  )
              ),
              new_shape,
          )
  
      return mulacc
  
file_path: tinygrad/tinygrad/runtime/ops_cpu.py
imports: import numpy
  from typing import Callable, Dict, Tuple
  from tinygrad.helpers import flat_mv
  from tinygrad.ops import BufferOps, UnaryOps, BinaryOps, TernaryOps, ReduceOps, MovementOps, Op
  from tinygrad.device import Interpreted, Allocator
label_desc: Use image node_id 2 for calling a global function with example usage: einsum_mulacc(einsum, get_strides, expand) and returns: mulacc, str, tuple,  tuple, expand