code: def limit_dims_to_max(
      self, global_max: List[int], local_max: List[int]
  ):
      # Check the global allocation limit, current the global_size will be flipped during codegen
      # and then padded right with 1s if its length < 3 which makes this part a bit awkward to write
      global_dims = self.first_reduce - self.local_dims
      if global_dims > 0:
          if global_max:
              tmp = global_max[:global_dims] + (
                  local_max[: self.local_dims] if local_max else []
              )
              if max(global_max) < max(self.full_shape[:global_dims]):
                  self.reshape_and_permute(
                      lambda x: self._limit_size(
                          x,
                          tmp
                          + [math.inf]
                          * (len(self.full_shape) - len(tmp)),
                      ),
                      None,
                  )
              assert max(global_max) >= max(
                  self.full_shape[:global_dims]
              ), f"device max allocation {max(self.full_shape[:global_dims])} exceeds global dim maximum {max(global_max)}"  # noqa: E501
          for i in range(global_dims - 1):
              if (
                  i < len(global_max)
                  and self.full_shape[i] > global_max[i]
              ):
                  order = list(range(len(self.full_shape)))
                  order[i], order[global_dims - 1] = (
                      order[global_dims - 1],
                      order[i],
                  )
                  self.reshape_and_permute(None, order)
                  if DEBUG >= 3:
                      print(
                          "permuted global dim",
                          order,
                          "due to allocation exceeds global limit",
                      )
  
imports: from __future__ import annotations
  import os, math, itertools
  from typing import NamedTuple, Optional, List, Tuple, cast, Dict, Union
  from tinygrad.ops import LazyOp, FlopCounter, get_lazyop_info, UnaryOps, BinaryOps, ReduceOps, MemBuffer, ConstBuffer, BufferOps
  from tinygrad.device import Device, Compiled
  from tinygrad.dtype import dtypes, ImageDType, DType
  from tinygrad.helpers import dedup, colored, ansilen, getenv, prod, DEBUG, round_up, all_int
  from tinygrad.shape.shapetracker import ShapeTracker, get_contraction
  from tinygrad.shape.symbolic import sint
  from tinygrad.shape.view import View, strides_for_shape
  from dataclasses import dataclass
  from enum import Enum, auto
label_desc: Use image node_id 24 for calling the Kernel obj's underlying member method code with example usage: obj.limit_dims_to_max(global_max, local_max) without return types