code: def copy_data_to_device(
      data: T, device: torch.device, *args: Any, **kwargs: Any
  ) -> T:
      """Function that recursively copies data to a torch.device.
  
      Args:
          data: The data to copy to device
          device: The device to which the data should be copied
          args: positional arguments that will be passed to the `to` call
          kwargs: keyword arguments that will be passed to the `to` call
  
      Returns:
          The data on the correct device
      """
  
      # Redundant isinstance(data, tuple) check is required here to make pyre happy
      if _is_named_tuple(data) and isinstance(data, tuple):
          return type(data)(
              **copy_data_to_device(
                  data._asdict(), device, *args, **kwargs
              )
          )
      elif isinstance(data, (list, tuple)):
          return type(data)(
              copy_data_to_device(e, device, *args, **kwargs)
              for e in data
          )
      elif isinstance(data, defaultdict):
          return type(data)(
              data.default_factory,
              {
                  k: copy_data_to_device(v, device, *args, **kwargs)
                  for k, v in data.items()
              },
          )
      elif isinstance(data, Mapping):
          return type(data)(
              {
                  k: copy_data_to_device(v, device, *args, **kwargs)
                  for k, v in data.items()
              }
          )
      elif is_dataclass(data) and not isinstance(data, type):
          new_data_class = type(data)(
              **{
                  field.name: copy_data_to_device(
                      getattr(data, field.name), device, *args, **kwargs
                  )
                  for field in fields(data)
                  if field.init
              }
          )
          for field in fields(data):
              if not field.init:
                  setattr(
                      new_data_class,
                      field.name,
                      copy_data_to_device(
                          getattr(data, field.name),
                          device,
                          *args,
                          **kwargs,
                      ),
                  )
          return new_data_class
      elif isinstance(data, _CopyableData):
          return data.to(device, *args, **kwargs)
      return data
  
imports: import logging
  import os
  import shutil
  import subprocess
  from collections import defaultdict
  from dataclasses import fields, is_dataclass
  from typing import Any, Dict, Mapping, TypeVar
  import torch
  from torchtnt.utils.version import is_torch_version_geq_1_12
  from typing_extensions import Protocol, runtime_checkable, TypedDict
label_desc: Use image node_id 3 for calling a global function with example usage: copy_data_to_device(data, device) and returns: data, type, type, type, type, new_data_class, data