code: def split_func_call(
      func: Callable,
      inputs: Union[ivy.Array, ivy.NativeArray],
      mode: str,
      /,
      *,
      max_chunk_size: Optional[int] = None,
      chunk_size: Optional[int] = None,
      input_axes: Union[int, Iterable[int]] = 0,
      output_axes: Optional[Union[int, Iterable[int]]] = None,
      stop_gradients: bool = False,
      device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None,
  ) -> Union[ivy.Array, ivy.NativeArray]:
      """Call a function by splitting its inputs along a given axis, and calling
      the function in chunks, rather than feeding the entire input array at once.
      This can be useful to reduce memory usage of the device the arrays are on.
  
      Parameters
      ----------
      func
          The function to be called.
      inputs
          A list of inputs to pass into the function.
      mode
          The mode by which to unify the return values, must be one of
          [ concat | mean | sum ]
      max_chunk_size
          The maximum size of each of the chunks to be fed into the function.
      chunk_size
          The size of each of the chunks to be fed into the function. Specifying this arg
          overwrites the global split factor. Default is ``None``.
      input_axes
          The axes along which to split each of the inputs, before passing to the
          function. Default is ``0``.
      output_axes
          The axes along which to concat each of the returned outputs. Default is same as
          fist input axis.
      stop_gradients
          Whether to stop the gradients for each computed return. Default is ``False``.
      device
          The device to set the split factor for. Sets the default device by default.
  
      Returns
      -------
      ret
          The return from the function, following input splitting and re-concattenation.
      """
      if isinstance(input_axes, int):
          input_axes = [input_axes] * len(inputs)
      if not ivy.exists(max_chunk_size) and not ivy.exists(chunk_size):
          shape_key = "_".join([str(inp.shape) for inp in inputs])
          if shape_key in max_chunk_sizes:
              max_chunk_size = max_chunk_sizes[shape_key]
          else:
              max_chunk_size = 0
          max_dim = max(
              inp.cont_shape[inp_ax]
              for inp, inp_ax in zip(inputs, input_axes)
          )
          if max_dim > max_chunk_size:
              max_chunk_sizes[shape_key] = max_dim
              max_chunk_size = max_dim
      chunk_size = ivy.default(
          chunk_size,
          default_val=lambda: 1
          + int(
              round(
                  (max_chunk_size - 1)
                  * ivy.split_factor(ivy.default_device(device))
              )
          ),
          with_callable=True,
      )
      dim_size = inputs[0].shape[input_axes[0]]
      if chunk_size >= dim_size:
          return func(*inputs)
      num_chunks = dim_size / chunk_size
      num_chunks_floored = math.floor(num_chunks)
      num_chunks_ceiled = math.ceil(num_chunks)
      chunk_sizes = [chunk_size] * num_chunks_floored
      if num_chunks != num_chunks_floored:
          chunk_sizes.append(dim_size - chunk_size * num_chunks_floored)
      inputs_split = [
          (
              ivy.split(
                  inp,
                  num_or_size_splits=chunk_sizes,
                  axis=input_axes[i],
                  with_remainder=True,
              )
              if ivy.is_array(inp)
              else inp.split(
                  num_or_size_splits=chunk_sizes,
                  axis=input_axes[i],
                  with_remainder=True,
              )
          )
          for i, inp in enumerate(inputs)
      ]
      is_mean = mode == "mean"
      is_sum = mode == "sum"
      post_fn = ivy.stop_gradient if stop_gradients else lambda x: x
      if is_mean or is_sum:
          sums = None
          for inps in zip(*inputs_split):
              if not sums:
                  sums = func(*inps)
                  sums = (
                      [post_fn(s) for s in sums]
                      if isinstance(sums, tuple)
                      else [post_fn(sums)]
                  )
              else:
                  ret = func(*inps)
                  if isinstance(ret, tuple):
                      for i, r in enumerate(ret):
                          sums[i] = sums[i] + post_fn(r)
                  else:
                      sums[0] = sums[0] + post_fn(ret)
          sums_or_means = (
              [s / num_chunks_ceiled for s in sums] if is_mean else sums
          )
          return (
              sums_or_means[0]
              if len(sums_or_means) == 1
              else tuple(sums_or_means)
          )
      rets = [func(*i) for i in zip(*inputs_split)]
      rets = [
          tuple(post_fn(r) for r in ret)
          if isinstance(ret, tuple)
          else (post_fn(ret),)
          for ret in rets
      ]
      num_outputs = len(rets[0])
      if output_axes is None:
          output_axes = [input_axes[0]] * num_outputs
      elif isinstance(output_axes, int):
          output_axes = [output_axes] * num_outputs
      ret = [
          ivy.concat([r[i] for r in rets], axis=output_axes[i])
          for i in range(num_outputs)
      ]
      return ret[0] if len(ret) == 1 else ret
  
imports: import os
  import gc
  import abc
  import math
  import psutil
  import warnings
  import types
  from typing import Type, Optional, Tuple
  from typing import Union, Callable, Iterable, Any
  import ivy
  from ivy.func_wrapper import handle_out_argument, to_native_arrays_and_back, inputs_to_native_arrays, handle_nestable, handle_array_like_without_promotion, handle_backend_invalid
  from ivy.utils.exceptions import handle_exceptions
label_desc: Use image node_id 27 for calling a global function with example usage: split_func_call() and returns: unknown, func, unknown