code: def timing(
      model,
      tokenizer,
      device,
      batch_size=1,
      prompt_length=512,
      nb_tokens=512,
      iterations=10,
  ):
      def synchronize(device):
          if device.type == "cuda":
              torch.cuda.synchronize()
          elif device.type == "mps":
              torch.mps.synchronize()
          else:
              torch.cpu.synchronize()
  
      def timing_event(device):
          if device.type == "cuda":
              return torch.cuda.Event(enable_timing=True)
          elif device.type == "mps":
              return torch.mps.Event(enable_timing=True)
  
          class CPUEvent:
              def __init__(self):
                  self.time = None
  
              def record(self):
                  self.time = time.time()
  
              def elapsed_time(self, other):
                  assert self.time is not None
                  assert other.time is not None
                  return (other.time - self.time) * 1000
  
          return CPUEvent()
  
      generation_config = GenerationConfig(
          max_new_tokens=nb_tokens,
          min_new_tokens=nb_tokens,
          use_cache=True,
          pad_token_id=tokenizer.pad_token_id,
          num_beams=1,
          do_sample=False,
          eos_token_id=None,  # This is required for min_new_tokens to actually have an effect.
      )
      model.generation_config.eos_token_id = None  # greedy_search falls back on this eos_token_id that we need to set to None as well for min_new_tokens to have an effect.
  
      synchronize(device)
  
      latencies = []
      input_ids = torch.randint(
          1,
          model.config.vocab_size - 1,
          size=(batch_size, prompt_length),
      ).to(device)
      masks = torch.ones(
          batch_size, prompt_length, dtype=torch.int32
      ).to(device)
  
      # mean over 10 batches
      for _ in tqdm(range(iterations)):
          start_event = timing_event(device)
          end_event = timing_event(device)
          synchronize(device)
          start_event.record()
  
          _ = model.generate(
              input_ids,
              attention_mask=masks,
              generation_config=generation_config,
          )
          end_event.record()
          synchronize(device)
  
          latency_ms = start_event.elapsed_time(end_event)
          latencies.append(latency_ms)
  
      return np.mean(latencies) / generation_config.min_new_tokens
  
file_path: quanto/bench/generation/benchmark.py
imports: import argparse
  import gc
  import time
  import numpy
  import torch
  from tqdm.auto import tqdm
  from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, GenerationConfig
  from quanto import Calibration, freeze, quantize
label_desc: Use image node_id 2 for calling a global function with example usage: timing(model, tokenizer, device, batch_size, prompt_length, nb_tokens, iterations) and returns: unknown, CPUEvent, torch, torch, unknown