prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Incorrect setting of persistent_workers hparam
  DataloaderHparams:
  `persistent_workers: bool = hp.optional("Whether to shutdown workers after the dataset has been consumed once",                                              default=True)`
  
  This makes it sound like the default option which is True shuts down the workers after the dataset has been consumed once. But when calling torch Dataloader, the default is False and this option keeps the workers alive.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `composer/datasets/dataloader.py`
  Content:
  ```
  1 # Copyright 2021 MosaicML. All Rights Reserved.
  2 
  3 from __future__ import annotations
  4 
  5 import logging
  6 import textwrap
  7 from dataclasses import dataclass
  8 from typing import Any, Callable, Iterator, Optional
  9 
  10 import torch
  11 import torch.distributed
  12 import torch.utils.data
  13 import yahp as hp
  14 
  15 from composer.core.types import Batch, DataLoader, Dataset
  16 
  17 log = logging.getLogger(__name__)
  18 
  19 
  20 class WrappedDataLoader(DataLoader):
  21 
  22     def __init__(self, dataloader: DataLoader) -> None:
  23         if self.is_dataloader_already_wrapped(dataloader):
  24             log.debug(
  25                 textwrap.dedent("""\
  26                     The dataloader is already wrapped with %s; it will be wrapped again.
  27                     If this is unintended behavior, guard the wrapping of the dataloader i.e. with:
  28                     if not %s.is_dataloader_already_wrapped(dataloader): dataloader = %s(dataloader)"""),
  29                 type(self).__name__,
  30                 type(self).__name__,
  31                 type(self).__name__,
  32             )
  33         self.dataset = dataloader.dataset
  34         self.batch_size = dataloader.batch_size
  35         self.num_workers = dataloader.num_workers
  36         self.pin_memory = dataloader.pin_memory
  37         self.drop_last = dataloader.drop_last
  38         self.timeout = dataloader.timeout
  39         self.sampler = dataloader.sampler
  40         self.prefetch_factor = dataloader.prefetch_factor
  41         self.dataloader = dataloader
  42 
  43     def __len__(self) -> int:
  44         return len(self.dataloader)
  45 
  46     def __iter__(self) -> Iterator[Batch]:
  47         return iter(self.dataloader)
  48 
  49     def __bool__(self) -> bool:
  50         return True
  51 
  52     def __setattr__(self, name: str, value: Any) -> None:
  53         if hasattr(self, name) and name in ("dataset", "batch_size", "num_workers", "pin_memory", "drop_last",
  54                                             "timeout", "sampler", "prefetch_factor", "dataloader"):
  55             raise RuntimeError(f"Property {name} cannot be set after initialization in a DataLoader")
  56         return super().__setattr__(name, value)
  57 
  58     @classmethod
  59     def is_dataloader_already_wrapped(cls, dataloader: DataLoader):
  60         """Returns whether the ``dataloader`` is wrapped with ``cls``. This helper method checks recursively through all
  61         wrappings until the underlying dataloader is reached.
  62 
  63         Args:
  64             dataloader (DataLoader): The dataloader to check
  65 
  66         Returns:
  67             bool: Whether the ``dataloader`` is wrapped recursively with ``cls``.
  68         """
  69         if isinstance(dataloader, cls):
  70             return True
  71         if not isinstance(dataloader, WrappedDataLoader):
  72             return False
  73         if not isinstance(dataloader.dataloader, WrappedDataLoader):
  74             return False
  75         return cls.is_dataloader_already_wrapped(dataloader.dataloader)
  76 
  77 
  78 def unwrap_data_loader(dataloader: DataLoader) -> DataLoader:
  79     """Recursively unwraps a dataloader if it is of type :class:`WrappedDataLoader`.
  80 
  81     Args:
  82         dataloader (DataLoader): The dataloader to unwrap
  83 
  84     Returns:
  85         DataLoader: The underlying dataloader
  86     """
  87     if isinstance(dataloader, WrappedDataLoader):
  88         return unwrap_data_loader(dataloader.dataloader)
  89     return dataloader
  90 
  91 
  92 @dataclass
  93 class DataloaderHparams(hp.Hparams):
  94     """Hyperparameters to initialize a :class:`~torch.utils.data.Dataloader`.
  95 
  96     Parameters:
  97         num_workers (int): Number of CPU workers to use per device to fetch data.
  98         prefetch_factor (int): Number of samples loaded in advance by each worker.
  99             2 means there will be a total of 2 * num_workers samples prefetched across all workers.
  100         persistent_workers (bool): Whether or not to shutdown workers after the dataset has been consumed once.
  101         pin_memory (bool): Whether or not to copy Tensors into CUDA pinned memory before returning them.
  102         timeout (float): Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout.
  103     """
  104 
  105     num_workers: int = hp.optional("Number of CPU workers to use per device to fetch data.", default=8)
  106     prefetch_factor: int = hp.optional("Number of samples loaded in advance by each worker", default=2)
  107     persistent_workers: bool = hp.optional("Whether to shutdown workers after the dataset has been consumed once",
  108                                            default=True)
  109     pin_memory: bool = hp.optional("Whether to copy Tensors into CUDA pinned memory before returning them",
  110                                    default=True)
  111     timeout: float = hp.optional("Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout",
  112                                  default=0)
  113 
  114     def initialize_object(
  115         self,
  116         dataset: Dataset,
  117         *,
  118         batch_size: int,
  119         sampler: Optional[torch.utils.data.Sampler[int]],
  120         drop_last: bool,
  121         collate_fn: Optional[Callable] = None,
  122         worker_init_fn: Optional[Callable] = None,
  123     ) -> DataLoader:
  124         """Create a dataloader.
  125 
  126         Args:
  127             dataset (Dataset): The dataset.
  128             batch_size (int): The per-device batch size.
  129             sampler (torch.utils.data.Sampler[int] or None): The sampler to use for the dataloader.
  130             drop_last (bool): Whether to drop the last batch if the number of
  131                 samples is not evenly divisible by the batch size.
  132             collate_fn (callable, optional): Custom collate function. Defaults to None.
  133             worker_init_fn (callable, optional): Custom worker init function. Defaults to None.
  134 
  135         Returns:
  136             DataLoader: The dataloader.
  137         """
  138 
  139         return torch.utils.data.DataLoader(dataset,
  140                                            batch_size=batch_size,
  141                                            num_workers=self.num_workers,
  142                                            pin_memory=self.pin_memory,
  143                                            drop_last=drop_last,
  144                                            sampler=sampler,
  145                                            collate_fn=collate_fn,
  146                                            worker_init_fn=worker_init_fn,
  147                                            timeout=self.timeout,
  148                                            prefetch_factor=self.prefetch_factor,
  149                                            persistent_workers=self.persistent_workers)
  150
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/composer/datasets/dataloader.py b/composer/datasets/dataloader.py
  --- a/composer/datasets/dataloader.py
  +++ b/composer/datasets/dataloader.py
  @@ -94,22 +94,42 @@
       """Hyperparameters to initialize a :class:`~torch.utils.data.Dataloader`.
   
       Parameters:
  -        num_workers (int): Number of CPU workers to use per device to fetch data.
  -        prefetch_factor (int): Number of samples loaded in advance by each worker.
  -            2 means there will be a total of 2 * num_workers samples prefetched across all workers.
  -        persistent_workers (bool): Whether or not to shutdown workers after the dataset has been consumed once.
  -        pin_memory (bool): Whether or not to copy Tensors into CUDA pinned memory before returning them.
  -        timeout (float): Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout.
  +        num_workers (int, optional): Number of CPU workers to use per device to fetch data.
  +            Set to ``0`` to use the main training thread for dataloading.
  +            While zero workers can be useful for debugging, it should not be used for performance reasons.
  +            (default: ``8``)
  +        prefetch_factor (int, optional): Number of samples loaded in advance by each worker.
  +            For example, 2 means there will be a total of 2 * num_workers samples prefetched across all workers.
  +            If ``num_workers = 0``, then the ``prefetch_factor`` must be left at the default value.
  +            (default: ``2``)
  +        persistent_workers (bool): Whether to reuse dataloader workers across epochs. If ``num_workers`` is 0,
  +            then this field must be ``False``. (default: ``True``)
  +        pin_memory (bool, optional): Whether or not to copy Tensors into CUDA pinned memory before returning them.
  +            If ``num_workers = 0``, then the ``pin_memory`` must be ``False``. (default: ``True``)
  +        timeout (float): Timeout, in seconds, for collecting a batch from workers. Set to ``0`` for no timeout.
  +            (default: ``0``)
       """
   
  -    num_workers: int = hp.optional("Number of CPU workers to use per device to fetch data.", default=8)
  -    prefetch_factor: int = hp.optional("Number of samples loaded in advance by each worker", default=2)
  -    persistent_workers: bool = hp.optional("Whether to shutdown workers after the dataset has been consumed once",
  +    num_workers: int = hp.optional(textwrap.dedent("""\
  +        Number of CPU workers to use per device to fetch data.
  +        Set to ``0`` to use the main training thread for dataloading.
  +        While zero workers can be useful for debugging, it should not be used for performance reasons."""),
  +                                   default=8)
  +    prefetch_factor: int = hp.optional(textwrap.dedent("""\
  +        Number of samples loaded in advance by each worker.
  +        For example, 2 means there will be a total of 2 * num_workers samples prefetched across all workers.
  +        If ``num_workers = 0``, then the ``prefetch_factor`` must be left at the default value."""),
  +                                       default=2)
  +    persistent_workers: bool = hp.optional(textwrap.dedent("""\
  +         Whether to reuse dataloader workers across epochs. If ``num_workers`` is 0,
  +            then this field must be ``False``"""),
                                              default=True)
  -    pin_memory: bool = hp.optional("Whether to copy Tensors into CUDA pinned memory before returning them",
  +    pin_memory: bool = hp.optional(textwrap.dedent("""\
  +            Whether or not to copy Tensors into CUDA pinned memory before returning them.
  +            If ``num_workers = 0``, then the ``pin_memory`` must be ``False``."""),
                                      default=True)
  -    timeout: float = hp.optional("Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout",
  -                                 default=0)
  +    timeout: float = hp.optional(
  +        "Timeout, in seconds, for collecting a batch from workers. Set to ``0`` for no timeout.", default=0)
   
       def initialize_object(
           self,
  
verification_info: {"golden_diff": "diff --git a/composer/datasets/dataloader.py b/composer/datasets/dataloader.py\n--- a/composer/datasets/dataloader.py\n+++ b/composer/datasets/dataloader.py\n@@ -94,22 +94,42 @@\n     \"\"\"Hyperparameters to initialize a :class:`~torch.utils.data.Dataloader`.\n \n     Parameters:\n-        num_workers (int): Number of CPU workers to use per device to fetch data.\n-        prefetch_factor (int): Number of samples loaded in advance by each worker.\n-            2 means there will be a total of 2 * num_workers samples prefetched across all workers.\n-        persistent_workers (bool): Whether or not to shutdown workers after the dataset has been consumed once.\n-        pin_memory (bool): Whether or not to copy Tensors into CUDA pinned memory before returning them.\n-        timeout (float): Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout.\n+        num_workers (int, optional): Number of CPU workers to use per device to fetch data.\n+            Set to ``0`` to use the main training thread for dataloading.\n+            While zero workers can be useful for debugging, it should not be used for performance reasons.\n+            (default: ``8``)\n+        prefetch_factor (int, optional): Number of samples loaded in advance by each worker.\n+            For example, 2 means there will be a total of 2 * num_workers samples prefetched across all workers.\n+            If ``num_workers = 0``, then the ``prefetch_factor`` must be left at the default value.\n+            (default: ``2``)\n+        persistent_workers (bool): Whether to reuse dataloader workers across epochs. If ``num_workers`` is 0,\n+            then this field must be ``False``. (default: ``True``)\n+        pin_memory (bool, optional): Whether or not to copy Tensors into CUDA pinned memory before returning them.\n+            If ``num_workers = 0``, then the ``pin_memory`` must be ``False``. (default: ``True``)\n+        timeout (float): Timeout, in seconds, for collecting a batch from workers. Set to ``0`` for no timeout.\n+            (default: ``0``)\n     \"\"\"\n \n-    num_workers: int = hp.optional(\"Number of CPU workers to use per device to fetch data.\", default=8)\n-    prefetch_factor: int = hp.optional(\"Number of samples loaded in advance by each worker\", default=2)\n-    persistent_workers: bool = hp.optional(\"Whether to shutdown workers after the dataset has been consumed once\",\n+    num_workers: int = hp.optional(textwrap.dedent(\"\"\"\\\n+        Number of CPU workers to use per device to fetch data.\n+        Set to ``0`` to use the main training thread for dataloading.\n+        While zero workers can be useful for debugging, it should not be used for performance reasons.\"\"\"),\n+                                   default=8)\n+    prefetch_factor: int = hp.optional(textwrap.dedent(\"\"\"\\\n+        Number of samples loaded in advance by each worker.\n+        For example, 2 means there will be a total of 2 * num_workers samples prefetched across all workers.\n+        If ``num_workers = 0``, then the ``prefetch_factor`` must be left at the default value.\"\"\"),\n+                                       default=2)\n+    persistent_workers: bool = hp.optional(textwrap.dedent(\"\"\"\\\n+         Whether to reuse dataloader workers across epochs. If ``num_workers`` is 0,\n+            then this field must be ``False``\"\"\"),\n                                            default=True)\n-    pin_memory: bool = hp.optional(\"Whether to copy Tensors into CUDA pinned memory before returning them\",\n+    pin_memory: bool = hp.optional(textwrap.dedent(\"\"\"\\\n+            Whether or not to copy Tensors into CUDA pinned memory before returning them.\n+            If ``num_workers = 0``, then the ``pin_memory`` must be ``False``.\"\"\"),\n                                    default=True)\n-    timeout: float = hp.optional(\"Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout\",\n-                                 default=0)\n+    timeout: float = hp.optional(\n+        \"Timeout, in seconds, for collecting a batch from workers. Set to ``0`` for no timeout.\", default=0)\n \n     def initialize_object(\n         self,\n", "issue": "Incorrect setting of persistent_workers hparam\nDataloaderHparams:\r\n`persistent_workers: bool = hp.optional(\"Whether to shutdown workers after the dataset has been consumed once\",                                              default=True)`\r\n\r\nThis makes it sound like the default option which is True shuts down the workers after the dataset has been consumed once. But when calling torch Dataloader, the default is False and this option keeps the workers alive.\n", "before_files": [{"content": "# Copyright 2021 MosaicML. All Rights Reserved.\n\nfrom __future__ import annotations\n\nimport logging\nimport textwrap\nfrom dataclasses import dataclass\nfrom typing import Any, Callable, Iterator, Optional\n\nimport torch\nimport torch.distributed\nimport torch.utils.data\nimport yahp as hp\n\nfrom composer.core.types import Batch, DataLoader, Dataset\n\nlog = logging.getLogger(__name__)\n\n\nclass WrappedDataLoader(DataLoader):\n\n    def __init__(self, dataloader: DataLoader) -> None:\n        if self.is_dataloader_already_wrapped(dataloader):\n            log.debug(\n                textwrap.dedent(\"\"\"\\\n                    The dataloader is already wrapped with %s; it will be wrapped again.\n                    If this is unintended behavior, guard the wrapping of the dataloader i.e. with:\n                    if not %s.is_dataloader_already_wrapped(dataloader): dataloader = %s(dataloader)\"\"\"),\n                type(self).__name__,\n                type(self).__name__,\n                type(self).__name__,\n            )\n        self.dataset = dataloader.dataset\n        self.batch_size = dataloader.batch_size\n        self.num_workers = dataloader.num_workers\n        self.pin_memory = dataloader.pin_memory\n        self.drop_last = dataloader.drop_last\n        self.timeout = dataloader.timeout\n        self.sampler = dataloader.sampler\n        self.prefetch_factor = dataloader.prefetch_factor\n        self.dataloader = dataloader\n\n    def __len__(self) -> int:\n        return len(self.dataloader)\n\n    def __iter__(self) -> Iterator[Batch]:\n        return iter(self.dataloader)\n\n    def __bool__(self) -> bool:\n        return True\n\n    def __setattr__(self, name: str, value: Any) -> None:\n        if hasattr(self, name) and name in (\"dataset\", \"batch_size\", \"num_workers\", \"pin_memory\", \"drop_last\",\n                                            \"timeout\", \"sampler\", \"prefetch_factor\", \"dataloader\"):\n            raise RuntimeError(f\"Property {name} cannot be set after initialization in a DataLoader\")\n        return super().__setattr__(name, value)\n\n    @classmethod\n    def is_dataloader_already_wrapped(cls, dataloader: DataLoader):\n        \"\"\"Returns whether the ``dataloader`` is wrapped with ``cls``. This helper method checks recursively through all\n        wrappings until the underlying dataloader is reached.\n\n        Args:\n            dataloader (DataLoader): The dataloader to check\n\n        Returns:\n            bool: Whether the ``dataloader`` is wrapped recursively with ``cls``.\n        \"\"\"\n        if isinstance(dataloader, cls):\n            return True\n        if not isinstance(dataloader, WrappedDataLoader):\n            return False\n        if not isinstance(dataloader.dataloader, WrappedDataLoader):\n            return False\n        return cls.is_dataloader_already_wrapped(dataloader.dataloader)\n\n\ndef unwrap_data_loader(dataloader: DataLoader) -> DataLoader:\n    \"\"\"Recursively unwraps a dataloader if it is of type :class:`WrappedDataLoader`.\n\n    Args:\n        dataloader (DataLoader): The dataloader to unwrap\n\n    Returns:\n        DataLoader: The underlying dataloader\n    \"\"\"\n    if isinstance(dataloader, WrappedDataLoader):\n        return unwrap_data_loader(dataloader.dataloader)\n    return dataloader\n\n\n@dataclass\nclass DataloaderHparams(hp.Hparams):\n    \"\"\"Hyperparameters to initialize a :class:`~torch.utils.data.Dataloader`.\n\n    Parameters:\n        num_workers (int): Number of CPU workers to use per device to fetch data.\n        prefetch_factor (int): Number of samples loaded in advance by each worker.\n            2 means there will be a total of 2 * num_workers samples prefetched across all workers.\n        persistent_workers (bool): Whether or not to shutdown workers after the dataset has been consumed once.\n        pin_memory (bool): Whether or not to copy Tensors into CUDA pinned memory before returning them.\n        timeout (float): Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout.\n    \"\"\"\n\n    num_workers: int = hp.optional(\"Number of CPU workers to use per device to fetch data.\", default=8)\n    prefetch_factor: int = hp.optional(\"Number of samples loaded in advance by each worker\", default=2)\n    persistent_workers: bool = hp.optional(\"Whether to shutdown workers after the dataset has been consumed once\",\n                                           default=True)\n    pin_memory: bool = hp.optional(\"Whether to copy Tensors into CUDA pinned memory before returning them\",\n                                   default=True)\n    timeout: float = hp.optional(\"Timeout, in seconds, for collecting a batch from workers. Set to 0 for no timeout\",\n                                 default=0)\n\n    def initialize_object(\n        self,\n        dataset: Dataset,\n        *,\n        batch_size: int,\n        sampler: Optional[torch.utils.data.Sampler[int]],\n        drop_last: bool,\n        collate_fn: Optional[Callable] = None,\n        worker_init_fn: Optional[Callable] = None,\n    ) -> DataLoader:\n        \"\"\"Create a dataloader.\n\n        Args:\n            dataset (Dataset): The dataset.\n            batch_size (int): The per-device batch size.\n            sampler (torch.utils.data.Sampler[int] or None): The sampler to use for the dataloader.\n            drop_last (bool): Whether to drop the last batch if the number of\n                samples is not evenly divisible by the batch size.\n            collate_fn (callable, optional): Custom collate function. Defaults to None.\n            worker_init_fn (callable, optional): Custom worker init function. Defaults to None.\n\n        Returns:\n            DataLoader: The dataloader.\n        \"\"\"\n\n        return torch.utils.data.DataLoader(dataset,\n                                           batch_size=batch_size,\n                                           num_workers=self.num_workers,\n                                           pin_memory=self.pin_memory,\n                                           drop_last=drop_last,\n                                           sampler=sampler,\n                                           collate_fn=collate_fn,\n                                           worker_init_fn=worker_init_fn,\n                                           timeout=self.timeout,\n                                           prefetch_factor=self.prefetch_factor,\n                                           persistent_workers=self.persistent_workers)\n", "path": "composer/datasets/dataloader.py"}], "after_files": [{"content": "# Copyright 2021 MosaicML. All Rights Reserved.\n\nfrom __future__ import annotations\n\nimport logging\nimport textwrap\nfrom dataclasses import dataclass\nfrom typing import Any, Callable, Iterator, Optional\n\nimport torch\nimport torch.distributed\nimport torch.utils.data\nimport yahp as hp\n\nfrom composer.core.types import Batch, DataLoader, Dataset\n\nlog = logging.getLogger(__name__)\n\n\nclass WrappedDataLoader(DataLoader):\n\n    def __init__(self, dataloader: DataLoader) -> None:\n        if self.is_dataloader_already_wrapped(dataloader):\n            log.debug(\n                textwrap.dedent(\"\"\"\\\n                    The dataloader is already wrapped with %s; it will be wrapped again.\n                    If this is unintended behavior, guard the wrapping of the dataloader i.e. with:\n                    if not %s.is_dataloader_already_wrapped(dataloader): dataloader = %s(dataloader)\"\"\"),\n                type(self).__name__,\n                type(self).__name__,\n                type(self).__name__,\n            )\n        self.dataset = dataloader.dataset\n        self.batch_size = dataloader.batch_size\n        self.num_workers = dataloader.num_workers\n        self.pin_memory = dataloader.pin_memory\n        self.drop_last = dataloader.drop_last\n        self.timeout = dataloader.timeout\n        self.sampler = dataloader.sampler\n        self.prefetch_factor = dataloader.prefetch_factor\n        self.dataloader = dataloader\n\n    def __len__(self) -> int:\n        return len(self.dataloader)\n\n    def __iter__(self) -> Iterator[Batch]:\n        return iter(self.dataloader)\n\n    def __bool__(self) -> bool:\n        return True\n\n    def __setattr__(self, name: str, value: Any) -> None:\n        if hasattr(self, name) and name in (\"dataset\", \"batch_size\", \"num_workers\", \"pin_memory\", \"drop_last\",\n                                            \"timeout\", \"sampler\", \"prefetch_factor\", \"dataloader\"):\n            raise RuntimeError(f\"Property {name} cannot be set after initialization in a DataLoader\")\n        return super().__setattr__(name, value)\n\n    @classmethod\n    def is_dataloader_already_wrapped(cls, dataloader: DataLoader):\n        \"\"\"Returns whether the ``dataloader`` is wrapped with ``cls``. This helper method checks recursively through all\n        wrappings until the underlying dataloader is reached.\n\n        Args:\n            dataloader (DataLoader): The dataloader to check\n\n        Returns:\n            bool: Whether the ``dataloader`` is wrapped recursively with ``cls``.\n        \"\"\"\n        if isinstance(dataloader, cls):\n            return True\n        if not isinstance(dataloader, WrappedDataLoader):\n            return False\n        if not isinstance(dataloader.dataloader, WrappedDataLoader):\n            return False\n        return cls.is_dataloader_already_wrapped(dataloader.dataloader)\n\n\ndef unwrap_data_loader(dataloader: DataLoader) -> DataLoader:\n    \"\"\"Recursively unwraps a dataloader if it is of type :class:`WrappedDataLoader`.\n\n    Args:\n        dataloader (DataLoader): The dataloader to unwrap\n\n    Returns:\n        DataLoader: The underlying dataloader\n    \"\"\"\n    if isinstance(dataloader, WrappedDataLoader):\n        return unwrap_data_loader(dataloader.dataloader)\n    return dataloader\n\n\n@dataclass\nclass DataloaderHparams(hp.Hparams):\n    \"\"\"Hyperparameters to initialize a :class:`~torch.utils.data.Dataloader`.\n\n    Parameters:\n        num_workers (int, optional): Number of CPU workers to use per device to fetch data.\n            Set to ``0`` to use the main training thread for dataloading.\n            While zero workers can be useful for debugging, it should not be used for performance reasons.\n            (default: ``8``)\n        prefetch_factor (int, optional): Number of samples loaded in advance by each worker.\n            For example, 2 means there will be a total of 2 * num_workers samples prefetched across all workers.\n            If ``num_workers = 0``, then the ``prefetch_factor`` must be left at the default value.\n            (default: ``2``)\n        persistent_workers (bool): Whether to reuse dataloader workers across epochs. If ``num_workers`` is 0,\n            then this field must be ``False``. (default: ``True``)\n        pin_memory (bool, optional): Whether or not to copy Tensors into CUDA pinned memory before returning them.\n            If ``num_workers = 0``, then the ``pin_memory`` must be ``False``. (default: ``True``)\n        timeout (float): Timeout, in seconds, for collecting a batch from workers. Set to ``0`` for no timeout.\n            (default: ``0``)\n    \"\"\"\n\n    num_workers: int = hp.optional(textwrap.dedent(\"\"\"\\\n        Number of CPU workers to use per device to fetch data.\n        Set to ``0`` to use the main training thread for dataloading.\n        While zero workers can be useful for debugging, it should not be used for performance reasons.\"\"\"),\n                                   default=8)\n    prefetch_factor: int = hp.optional(textwrap.dedent(\"\"\"\\\n        Number of samples loaded in advance by each worker.\n        For example, 2 means there will be a total of 2 * num_workers samples prefetched across all workers.\n        If ``num_workers = 0``, then the ``prefetch_factor`` must be left at the default value.\"\"\"),\n                                       default=2)\n    persistent_workers: bool = hp.optional(textwrap.dedent(\"\"\"\\\n         Whether to reuse dataloader workers across epochs. If ``num_workers`` is 0,\n            then this field must be ``False``\"\"\"),\n                                           default=True)\n    pin_memory: bool = hp.optional(textwrap.dedent(\"\"\"\\\n            Whether or not to copy Tensors into CUDA pinned memory before returning them.\n            If ``num_workers = 0``, then the ``pin_memory`` must be ``False``.\"\"\"),\n                                   default=True)\n    timeout: float = hp.optional(\n        \"Timeout, in seconds, for collecting a batch from workers. Set to ``0`` for no timeout.\", default=0)\n\n    def initialize_object(\n        self,\n        dataset: Dataset,\n        *,\n        batch_size: int,\n        sampler: Optional[torch.utils.data.Sampler[int]],\n        drop_last: bool,\n        collate_fn: Optional[Callable] = None,\n        worker_init_fn: Optional[Callable] = None,\n    ) -> DataLoader:\n        \"\"\"Create a dataloader.\n\n        Args:\n            dataset (Dataset): The dataset.\n            batch_size (int): The per-device batch size.\n            sampler (torch.utils.data.Sampler[int] or None): The sampler to use for the dataloader.\n            drop_last (bool): Whether to drop the last batch if the number of\n                samples is not evenly divisible by the batch size.\n            collate_fn (callable, optional): Custom collate function. Defaults to None.\n            worker_init_fn (callable, optional): Custom worker init function. Defaults to None.\n\n        Returns:\n            DataLoader: The dataloader.\n        \"\"\"\n\n        return torch.utils.data.DataLoader(dataset,\n                                           batch_size=batch_size,\n                                           num_workers=self.num_workers,\n                                           pin_memory=self.pin_memory,\n                                           drop_last=drop_last,\n                                           sampler=sampler,\n                                           collate_fn=collate_fn,\n                                           worker_init_fn=worker_init_fn,\n                                           timeout=self.timeout,\n                                           prefetch_factor=self.prefetch_factor,\n                                           persistent_workers=self.persistent_workers)\n", "path": "composer/datasets/dataloader.py"}]}