prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [BUG]: Multi-rank on same device
  ### 🐛 Describe the bug
  
  When I use colossalai CLI with 2 node, I got an error "rank 8 and rank 0 both on CUDA device d000"
  I have examined my scripts and command. And torchrun works well.
  
  The error msg is:
  ```
  Error: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=0 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.64, is localhost: True, exception: I/O operation on closed file
  Error: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=1 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.189, is localhost: True, exception: I/O operation on closed file
  ```
  
  
  ### Environment
  
  _No response_
  [tensor] fix some unittests
  
  [tensor] fix some unittests
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `colossalai/cli/launcher/hostinfo.py`
  Content:
  ```
  1 import socket
  2 from typing import List
  3 
  4 
  5 class HostInfo:
  6     """
  7     A data class to store host connection-related data.
  8 
  9     Args:
  10         hostname (str): name or IP address of the host
  11         port (str): the port for ssh connection
  12     """
  13 
  14     def __init__(
  15         self,
  16         hostname: str,
  17         port: str = None,
  18     ):
  19         self.hostname = hostname
  20         self.port = port
  21         self.is_local_host = HostInfo.is_host_localhost(hostname, port)
  22 
  23     @staticmethod
  24     def is_host_localhost(hostname: str, port: str = None) -> None:
  25         """
  26         Check if the host refers to the local machine.
  27 
  28         Args:
  29             hostname (str): name or IP address of the host
  30             port (str): the port for ssh connection
  31 
  32         Returns:
  33             bool: True if it is local, False otherwise
  34         """
  35 
  36         if port is None:
  37             port = 22    # no port specified, lets just use the ssh port
  38 
  39         # socket.getfqdn("127.0.0.1") does not return localhost
  40         # on some users' machines
  41         # thus, we directly return True if hostname is localhost, 127.0.0.1 or 0.0.0.0
  42         if hostname in ("localhost", "127.0.0.1", "0.0.0.0"):
  43             return True
  44 
  45         hostname = socket.getfqdn(hostname)
  46         localhost = socket.gethostname()
  47         localaddrs = socket.getaddrinfo(localhost, port)
  48         targetaddrs = socket.getaddrinfo(hostname, port)
  49         for (family, socktype, proto, canonname, sockaddr) in localaddrs:
  50             for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:
  51                 if rsockaddr[0] == sockaddr[0]:
  52                     return True
  53         return False
  54 
  55     def __str__(self):
  56         return f'hostname: {self.hostname}, port: {self.port}'
  57 
  58     def __repr__(self):
  59         return self.__str__()
  60 
  61 
  62 class HostInfoList:
  63     """
  64     A data class to store a list of HostInfo objects.
  65     """
  66 
  67     def __init__(self):
  68         self.hostinfo_list = []
  69 
  70     def append(self, hostinfo: HostInfo) -> None:
  71         """
  72         Add an HostInfo object to the list.
  73 
  74         Args:
  75             hostinfo (HostInfo): host information
  76         """
  77 
  78         self.hostinfo_list.append(hostinfo)
  79 
  80     def remove(self, hostname: str) -> None:
  81         """
  82         Add an HostInfo object to the list.
  83 
  84         Args:
  85             hostname (str): the name of the host
  86         """
  87 
  88         hostinfo = self.get_hostinfo(hostname)
  89         self.hostinfo_list.remove(hostinfo)
  90 
  91     def get_hostinfo(self, hostname: str) -> HostInfo:
  92         """
  93         Return the HostInfo object which matches with the hostname.
  94 
  95         Args:
  96             hostname (str): the name of the host
  97 
  98         Returns:
  99             hostinfo (HostInfo): the HostInfo object which matches with the hostname
  100         """
  101 
  102         for hostinfo in self.hostinfo_list:
  103             if hostinfo.hostname == hostname:
  104                 return hostinfo
  105 
  106         raise Exception(f"Hostname {hostname} is not found")
  107 
  108     def has(self, hostname: str) -> bool:
  109         """
  110         Check if the hostname has been added.
  111 
  112         Args:
  113             hostname (str): the name of the host
  114 
  115         Returns:
  116             bool: True if added, False otherwise
  117         """
  118         for hostinfo in self.hostinfo_list:
  119             if hostinfo.hostname == hostname:
  120                 return True
  121         return False
  122 
  123     def __iter__(self):
  124         return iter(self.hostinfo_list)
  125 
  126     def __len__(self):
  127         return len(self.hostinfo_list)
  128
  ```
  --- 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/colossalai/cli/launcher/hostinfo.py b/colossalai/cli/launcher/hostinfo.py
  --- a/colossalai/cli/launcher/hostinfo.py
  +++ b/colossalai/cli/launcher/hostinfo.py
  @@ -46,11 +46,8 @@
           localhost = socket.gethostname()
           localaddrs = socket.getaddrinfo(localhost, port)
           targetaddrs = socket.getaddrinfo(hostname, port)
  -        for (family, socktype, proto, canonname, sockaddr) in localaddrs:
  -            for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:
  -                if rsockaddr[0] == sockaddr[0]:
  -                    return True
  -        return False
  +
  +        return localaddrs == targetaddrs
   
       def __str__(self):
           return f'hostname: {self.hostname}, port: {self.port}'
  
verification_info: {"golden_diff": "diff --git a/colossalai/cli/launcher/hostinfo.py b/colossalai/cli/launcher/hostinfo.py\n--- a/colossalai/cli/launcher/hostinfo.py\n+++ b/colossalai/cli/launcher/hostinfo.py\n@@ -46,11 +46,8 @@\n         localhost = socket.gethostname()\n         localaddrs = socket.getaddrinfo(localhost, port)\n         targetaddrs = socket.getaddrinfo(hostname, port)\n-        for (family, socktype, proto, canonname, sockaddr) in localaddrs:\n-            for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:\n-                if rsockaddr[0] == sockaddr[0]:\n-                    return True\n-        return False\n+\n+        return localaddrs == targetaddrs\n \n     def __str__(self):\n         return f'hostname: {self.hostname}, port: {self.port}'\n", "issue": "[BUG]: Multi-rank on same device\n### \ud83d\udc1b Describe the bug\n\nWhen I use colossalai CLI with 2 node, I got an error \"rank 8 and rank 0 both on CUDA device d000\"\r\nI have examined my scripts and command. And torchrun works well.\r\n\r\nThe error msg is:\r\n```\r\nError: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=0 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.64, is localhost: True, exception: I/O operation on closed file\r\nError: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=1 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.189, is localhost: True, exception: I/O operation on closed file\r\n```\r\n\n\n### Environment\n\n_No response_\n[tensor] fix some unittests\n\n[tensor] fix some unittests\n\n", "before_files": [{"content": "import socket\nfrom typing import List\n\n\nclass HostInfo:\n    \"\"\"\n    A data class to store host connection-related data.\n\n    Args:\n        hostname (str): name or IP address of the host\n        port (str): the port for ssh connection\n    \"\"\"\n\n    def __init__(\n        self,\n        hostname: str,\n        port: str = None,\n    ):\n        self.hostname = hostname\n        self.port = port\n        self.is_local_host = HostInfo.is_host_localhost(hostname, port)\n\n    @staticmethod\n    def is_host_localhost(hostname: str, port: str = None) -> None:\n        \"\"\"\n        Check if the host refers to the local machine.\n\n        Args:\n            hostname (str): name or IP address of the host\n            port (str): the port for ssh connection\n\n        Returns:\n            bool: True if it is local, False otherwise\n        \"\"\"\n\n        if port is None:\n            port = 22    # no port specified, lets just use the ssh port\n\n        # socket.getfqdn(\"127.0.0.1\") does not return localhost\n        # on some users' machines\n        # thus, we directly return True if hostname is localhost, 127.0.0.1 or 0.0.0.0\n        if hostname in (\"localhost\", \"127.0.0.1\", \"0.0.0.0\"):\n            return True\n\n        hostname = socket.getfqdn(hostname)\n        localhost = socket.gethostname()\n        localaddrs = socket.getaddrinfo(localhost, port)\n        targetaddrs = socket.getaddrinfo(hostname, port)\n        for (family, socktype, proto, canonname, sockaddr) in localaddrs:\n            for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:\n                if rsockaddr[0] == sockaddr[0]:\n                    return True\n        return False\n\n    def __str__(self):\n        return f'hostname: {self.hostname}, port: {self.port}'\n\n    def __repr__(self):\n        return self.__str__()\n\n\nclass HostInfoList:\n    \"\"\"\n    A data class to store a list of HostInfo objects.\n    \"\"\"\n\n    def __init__(self):\n        self.hostinfo_list = []\n\n    def append(self, hostinfo: HostInfo) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostinfo (HostInfo): host information\n        \"\"\"\n\n        self.hostinfo_list.append(hostinfo)\n\n    def remove(self, hostname: str) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostname (str): the name of the host\n        \"\"\"\n\n        hostinfo = self.get_hostinfo(hostname)\n        self.hostinfo_list.remove(hostinfo)\n\n    def get_hostinfo(self, hostname: str) -> HostInfo:\n        \"\"\"\n        Return the HostInfo object which matches with the hostname.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            hostinfo (HostInfo): the HostInfo object which matches with the hostname\n        \"\"\"\n\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return hostinfo\n\n        raise Exception(f\"Hostname {hostname} is not found\")\n\n    def has(self, hostname: str) -> bool:\n        \"\"\"\n        Check if the hostname has been added.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            bool: True if added, False otherwise\n        \"\"\"\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return True\n        return False\n\n    def __iter__(self):\n        return iter(self.hostinfo_list)\n\n    def __len__(self):\n        return len(self.hostinfo_list)\n", "path": "colossalai/cli/launcher/hostinfo.py"}], "after_files": [{"content": "import socket\nfrom typing import List\n\n\nclass HostInfo:\n    \"\"\"\n    A data class to store host connection-related data.\n\n    Args:\n        hostname (str): name or IP address of the host\n        port (str): the port for ssh connection\n    \"\"\"\n\n    def __init__(\n        self,\n        hostname: str,\n        port: str = None,\n    ):\n        self.hostname = hostname\n        self.port = port\n        self.is_local_host = HostInfo.is_host_localhost(hostname, port)\n\n    @staticmethod\n    def is_host_localhost(hostname: str, port: str = None) -> None:\n        \"\"\"\n        Check if the host refers to the local machine.\n\n        Args:\n            hostname (str): name or IP address of the host\n            port (str): the port for ssh connection\n\n        Returns:\n            bool: True if it is local, False otherwise\n        \"\"\"\n\n        if port is None:\n            port = 22    # no port specified, lets just use the ssh port\n\n        # socket.getfqdn(\"127.0.0.1\") does not return localhost\n        # on some users' machines\n        # thus, we directly return True if hostname is localhost, 127.0.0.1 or 0.0.0.0\n        if hostname in (\"localhost\", \"127.0.0.1\", \"0.0.0.0\"):\n            return True\n\n        hostname = socket.getfqdn(hostname)\n        localhost = socket.gethostname()\n        localaddrs = socket.getaddrinfo(localhost, port)\n        targetaddrs = socket.getaddrinfo(hostname, port)\n\n        return localaddrs == targetaddrs\n\n    def __str__(self):\n        return f'hostname: {self.hostname}, port: {self.port}'\n\n    def __repr__(self):\n        return self.__str__()\n\n\nclass HostInfoList:\n    \"\"\"\n    A data class to store a list of HostInfo objects.\n    \"\"\"\n\n    def __init__(self):\n        self.hostinfo_list = []\n\n    def append(self, hostinfo: HostInfo) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostinfo (HostInfo): host information\n        \"\"\"\n\n        self.hostinfo_list.append(hostinfo)\n\n    def remove(self, hostname: str) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostname (str): the name of the host\n        \"\"\"\n\n        hostinfo = self.get_hostinfo(hostname)\n        self.hostinfo_list.remove(hostinfo)\n\n    def get_hostinfo(self, hostname: str) -> HostInfo:\n        \"\"\"\n        Return the HostInfo object which matches with the hostname.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            hostinfo (HostInfo): the HostInfo object which matches with the hostname\n        \"\"\"\n\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return hostinfo\n\n        raise Exception(f\"Hostname {hostname} is not found\")\n\n    def has(self, hostname: str) -> bool:\n        \"\"\"\n        Check if the hostname has been added.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            bool: True if added, False otherwise\n        \"\"\"\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return True\n        return False\n\n    def __iter__(self):\n        return iter(self.hostinfo_list)\n\n    def __len__(self):\n        return len(self.hostinfo_list)\n", "path": "colossalai/cli/launcher/hostinfo.py"}]}