We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Summary not working for model on GPU with multiple inputs
**Describe the bug**
When you want a summary for a model that requires multiple input parameters for forward, then this doesn't work. You can set self.example_input_array to be a tuple and there is some code for passing this to the forward method. However, if the model is on cuda, it tries to pass to move this input directly to cuda without a check whether it is a tuple or list.

the line with the error is here: 
[pytorch-lightning/blob/master/pytorch_lightning/root_module/memory.py#L53](https://github.com/williamFalcon/pytorch-lightning/blob/7324dd902b8d071f4889ab1274a4d4dc09de9a78/pytorch_lightning/root_module/memory.py#L53)

example of how it should be checked: 
[pytorch-lightning/blob/master/pytorch_lightning/root_module/memory.py#L61](https://github.com/williamFalcon/pytorch-lightning/blob/7324dd902b8d071f4889ab1274a4d4dc09de9a78/pytorch_lightning/root_module/memory.py#L61)

**To Reproduce**
Steps to reproduce the behavior:
1. create a model that requires multiple inputs in the forward method. 
2. set self.example_input_array to be a tuple
3. run the model on GPU

**Expected behavior**
a list with all layers and the input and output shapes of these layers. 

**Screenshots**
![image](https://user-images.githubusercontent.com/6348139/69352469-4bc70180-0c7d-11ea-88c6-8056ab531c80.png)

**Desktop (please complete the following information):**
 - OS: Linux Mint 19.2
 - Browser chrome
 - Version 8.0.3904.97 (Official Build) (64-bit)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pytorch_lightning/core/memory.py`
Content:
```
1 '''
2 Generates a summary of a model's layers and dimensionality
3 '''
4 
5 import gc
6 import os
7 import subprocess
8 
9 import numpy as np
10 import pandas as pd
11 import torch
12 import logging
13 
14 
15 class ModelSummary(object):
16 
17     def __init__(self, model, mode='full'):
18         '''
19         Generates summaries of model layers and dimensions.
20         '''
21         self.model = model
22         self.mode = mode
23         self.in_sizes = []
24         self.out_sizes = []
25 
26         self.summarize()
27 
28     def __str__(self):
29         return self.summary.__str__()
30 
31     def __repr__(self):
32         return self.summary.__str__()
33 
34     def named_modules(self):
35         if self.mode == 'full':
36             mods = self.model.named_modules()
37             mods = list(mods)[1:]  # do not include root module (LightningModule)
38         elif self.mode == 'top':
39             # the children are the top-level modules
40             mods = self.model.named_children()
41         else:
42             mods = []
43         return list(mods)
44 
45     def get_variable_sizes(self):
46         '''Run sample input through each layer to get output sizes'''
47         mods = self.named_modules()
48         in_sizes = []
49         out_sizes = []
50         input_ = self.model.example_input_array
51 
52         if self.model.on_gpu:
53             input_ = input_.cuda(0)
54 
55         if self.model.trainer.use_amp:
56             input_ = input_.half()
57 
58         with torch.no_grad():
59 
60             for _, m in mods:
61                 if type(input_) is list or type(input_) is tuple:  # pragma: no cover
62                     out = m(*input_)
63                 else:
64                     out = m(input_)
65 
66                 if type(input_) is tuple or type(input_) is list:  # pragma: no cover
67                     in_size = []
68                     for x in input_:
69                         if type(x) is list:
70                             in_size.append(len(x))
71                         else:
72                             in_size.append(x.size())
73                 else:
74                     in_size = np.array(input_.size())
75 
76                 in_sizes.append(in_size)
77 
78                 if type(out) is tuple or type(out) is list:  # pragma: no cover
79                     out_size = np.asarray([x.size() for x in out])
80                 else:
81                     out_size = np.array(out.size())
82 
83                 out_sizes.append(out_size)
84                 input_ = out
85 
86         self.in_sizes = in_sizes
87         self.out_sizes = out_sizes
88         assert len(in_sizes) == len(out_sizes)
89         return
90 
91     def get_layer_names(self):
92         '''Collect Layer Names'''
93         mods = self.named_modules()
94         names = []
95         layers = []
96         for name, m in mods:
97             names += [name]
98             layers += [str(m.__class__)]
99 
100         layer_types = [x.split('.')[-1][:-2] for x in layers]
101 
102         self.layer_names = names
103         self.layer_types = layer_types
104         return
105 
106     def get_parameter_sizes(self):
107         '''Get sizes of all parameters in `model`'''
108         mods = self.named_modules()
109         sizes = []
110         for _, m in mods:
111             p = list(m.parameters())
112             modsz = []
113             for j in range(len(p)):
114                 modsz.append(np.array(p[j].size()))
115             sizes.append(modsz)
116 
117         self.param_sizes = sizes
118         return
119 
120     def get_parameter_nums(self):
121         '''Get number of parameters in each layer'''
122         param_nums = []
123         for mod in self.param_sizes:
124             all_params = 0
125             for p in mod:
126                 all_params += np.prod(p)
127             param_nums.append(all_params)
128         self.param_nums = param_nums
129         return
130 
131     def make_summary(self):
132         '''
133         Makes a summary listing with:
134 
135         Layer Name, Layer Type, Input Size, Output Size, Number of Parameters
136         '''
137 
138         cols = ['Name', 'Type', 'Params']
139         if self.model.example_input_array is not None:
140             cols.extend(['In_sizes', 'Out_sizes'])
141 
142         df = pd.DataFrame(np.zeros((len(self.layer_names), len(cols))))
143         df.columns = cols
144 
145         df['Name'] = self.layer_names
146         df['Type'] = self.layer_types
147         df['Params'] = self.param_nums
148         df['Params'] = df['Params'].map(get_human_readable_count)
149 
150         if self.model.example_input_array is not None:
151             df['In_sizes'] = self.in_sizes
152             df['Out_sizes'] = self.out_sizes
153 
154         self.summary = df
155         return
156 
157     def summarize(self):
158         self.get_layer_names()
159         self.get_parameter_sizes()
160         self.get_parameter_nums()
161 
162         if self.model.example_input_array is not None:
163             self.get_variable_sizes()
164         self.make_summary()
165 
166 
167 def print_mem_stack():  # pragma: no cover
168     for obj in gc.get_objects():
169         try:
170             if torch.is_tensor(obj) or (hasattr(obj, 'data') and torch.is_tensor(obj.data)):
171                 logging.info(type(obj), obj.size())
172         except Exception:
173             pass
174 
175 
176 def count_mem_items():  # pragma: no cover
177     num_params = 0
178     num_tensors = 0
179     for obj in gc.get_objects():
180         try:
181             if torch.is_tensor(obj) or (hasattr(obj, 'data') and torch.is_tensor(obj.data)):
182                 obj_type = str(type(obj))
183                 if 'parameter' in obj_type:
184                     num_params += 1
185                 else:
186                     num_tensors += 1
187         except Exception:
188             pass
189 
190     return num_params, num_tensors
191 
192 
193 def get_memory_profile(mode):
194     """
195     'all' means return memory for all gpus
196     'min_max' means return memory for max and min
197     :param mode:
198     :return:
199     """
200     memory_map = get_gpu_memory_map()
201 
202     if mode == 'min_max':
203         min_index, min_memory = min(memory_map.items(), key=lambda item: item[1])
204         max_index, max_memory = max(memory_map.items(), key=lambda item: item[1])
205 
206         memory_map = {min_index: min_memory, max_index: max_memory}
207 
208     return memory_map
209 
210 
211 def get_gpu_memory_map():
212     """Get the current gpu usage.
213 
214     Returns
215     -------
216     usage: dict
217         Keys are device ids as integers.
218         Values are memory usage as integers in MB.
219     """
220     result = subprocess.run(
221         [
222             'nvidia-smi',
223             '--query-gpu=memory.used',
224             '--format=csv,nounits,noheader',
225         ],
226         encoding='utf-8',
227         capture_output=True,
228         check=True)
229     # Convert lines into a dictionary
230     gpu_memory = [int(x) for x in result.stdout.strip().split(os.linesep)]
231     gpu_memory_map = {f'gpu_{index}': memory for index, memory in enumerate(gpu_memory)}
232     return gpu_memory_map
233 
234 
235 def get_human_readable_count(number):
236     """
237     Abbreviates an integer number with K, M, B, T for thousands, millions,
238     billions and trillions, respectively.
239     Examples:
240         123     -> 123
241         1234    -> 1 K       (one thousand)
242         2e6     -> 2 M       (two million)
243         3e9     -> 3 B       (three billion)
244         4e12    -> 4 T       (four trillion)
245         5e15    -> 5,000 T
246     :param number: a positive integer number
247     :returns a string formatted according to the pattern described above.
248     """
249     assert number >= 0
250     labels = [' ', 'K', 'M', 'B', 'T']
251     num_digits = int(np.floor(np.log10(number)) + 1 if number > 0 else 1)
252     num_groups = int(np.ceil(num_digits / 3))
253     num_groups = min(num_groups, len(labels))  # don't abbreviate beyond trillions
254     shift = -3 * (num_groups - 1)
255     number = number * (10 ** shift)
256     index = num_groups - 1
257     return f'{int(number):,d} {labels[index]}'
258
```
--- 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()

```

diff --git a/pytorch_lightning/core/memory.py b/pytorch_lightning/core/memory.py
--- a/pytorch_lightning/core/memory.py
+++ b/pytorch_lightning/core/memory.py
@@ -50,20 +50,31 @@
         input_ = self.model.example_input_array
 
         if self.model.on_gpu:
-            input_ = input_.cuda(0)
+            device = next(self.model.parameters()).get_device()
+            # test if input is a list or a tuple
+            if isinstance(input_, (list, tuple)):
+                input_ = [input_i.cuda(device) if torch.is_tensor(input_i) else input_i
+                          for input_i in input_]
+            else:
+                input_ = input_.cuda(device)
 
         if self.model.trainer.use_amp:
-            input_ = input_.half()
+            # test if it is not a list or a tuple
+            if isinstance(input_, (list, tuple)):
+                input_ = [input_i.half() if torch.is_tensor(input_i) else input_i
+                          for input_i in input_]
+            else:
+                input_ = input_.half()
 
         with torch.no_grad():
 
             for _, m in mods:
-                if type(input_) is list or type(input_) is tuple:  # pragma: no cover
+                if isinstance(input_, (list, tuple)):  # pragma: no cover
                     out = m(*input_)
                 else:
                     out = m(input_)
 
-                if type(input_) is tuple or type(input_) is list:  # pragma: no cover
+                if isinstance(input_, (list, tuple)):  # pragma: no cover
                     in_size = []
                     for x in input_:
                         if type(x) is list:
@@ -75,7 +86,7 @@
 
                 in_sizes.append(in_size)
 
-                if type(out) is tuple or type(out) is list:  # pragma: no cover
+                if isinstance(out, (list, tuple)):  # pragma: no cover
                     out_size = np.asarray([x.size() for x in out])
                 else:
                     out_size = np.array(out.size())

{"golden_diff": "diff --git a/pytorch_lightning/core/memory.py b/pytorch_lightning/core/memory.py\n--- a/pytorch_lightning/core/memory.py\n+++ b/pytorch_lightning/core/memory.py\n@@ -50,20 +50,31 @@\n         input_ = self.model.example_input_array\n \n         if self.model.on_gpu:\n-            input_ = input_.cuda(0)\n+            device = next(self.model.parameters()).get_device()\n+            # test if input is a list or a tuple\n+            if isinstance(input_, (list, tuple)):\n+                input_ = [input_i.cuda(device) if torch.is_tensor(input_i) else input_i\n+                          for input_i in input_]\n+            else:\n+                input_ = input_.cuda(device)\n \n         if self.model.trainer.use_amp:\n-            input_ = input_.half()\n+            # test if it is not a list or a tuple\n+            if isinstance(input_, (list, tuple)):\n+                input_ = [input_i.half() if torch.is_tensor(input_i) else input_i\n+                          for input_i in input_]\n+            else:\n+                input_ = input_.half()\n \n         with torch.no_grad():\n \n             for _, m in mods:\n-                if type(input_) is list or type(input_) is tuple:  # pragma: no cover\n+                if isinstance(input_, (list, tuple)):  # pragma: no cover\n                     out = m(*input_)\n                 else:\n                     out = m(input_)\n \n-                if type(input_) is tuple or type(input_) is list:  # pragma: no cover\n+                if isinstance(input_, (list, tuple)):  # pragma: no cover\n                     in_size = []\n                     for x in input_:\n                         if type(x) is list:\n@@ -75,7 +86,7 @@\n \n                 in_sizes.append(in_size)\n \n-                if type(out) is tuple or type(out) is list:  # pragma: no cover\n+                if isinstance(out, (list, tuple)):  # pragma: no cover\n                     out_size = np.asarray([x.size() for x in out])\n                 else:\n                     out_size = np.array(out.size())\n", "issue": "Summary not working for model on GPU with multiple inputs\n**Describe the bug**\r\nWhen you want a summary for a model that requires multiple input parameters for forward, then this doesn't work. You can set self.example_input_array to be a tuple and there is some code for passing this to the forward method. However, if the model is on cuda, it tries to pass to move this input directly to cuda without a check whether it is a tuple or list.\r\n\r\nthe line with the error is here: \r\n[pytorch-lightning/blob/master/pytorch_lightning/root_module/memory.py#L53](https://github.com/williamFalcon/pytorch-lightning/blob/7324dd902b8d071f4889ab1274a4d4dc09de9a78/pytorch_lightning/root_module/memory.py#L53)\r\n\r\nexample of how it should be checked: \r\n[pytorch-lightning/blob/master/pytorch_lightning/root_module/memory.py#L61](https://github.com/williamFalcon/pytorch-lightning/blob/7324dd902b8d071f4889ab1274a4d4dc09de9a78/pytorch_lightning/root_module/memory.py#L61)\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n1. create a model that requires multiple inputs in the forward method. \r\n2. set self.example_input_array to be a tuple\r\n3. run the model on GPU\r\n\r\n**Expected behavior**\r\na list with all layers and the input and output shapes of these layers. \r\n\r\n**Screenshots**\r\n![image](https://user-images.githubusercontent.com/6348139/69352469-4bc70180-0c7d-11ea-88c6-8056ab531c80.png)\r\n\r\n**Desktop (please complete the following information):**\r\n - OS: Linux Mint 19.2\r\n - Browser chrome\r\n - Version 8.0.3904.97 (Official Build) (64-bit)\r\n\n", "before_files": [{"content": "'''\nGenerates a summary of a model's layers and dimensionality\n'''\n\nimport gc\nimport os\nimport subprocess\n\nimport numpy as np\nimport pandas as pd\nimport torch\nimport logging\n\n\nclass ModelSummary(object):\n\n    def __init__(self, model, mode='full'):\n        '''\n        Generates summaries of model layers and dimensions.\n        '''\n        self.model = model\n        self.mode = mode\n        self.in_sizes = []\n        self.out_sizes = []\n\n        self.summarize()\n\n    def __str__(self):\n        return self.summary.__str__()\n\n    def __repr__(self):\n        return self.summary.__str__()\n\n    def named_modules(self):\n        if self.mode == 'full':\n            mods = self.model.named_modules()\n            mods = list(mods)[1:]  # do not include root module (LightningModule)\n        elif self.mode == 'top':\n            # the children are the top-level modules\n            mods = self.model.named_children()\n        else:\n            mods = []\n        return list(mods)\n\n    def get_variable_sizes(self):\n        '''Run sample input through each layer to get output sizes'''\n        mods = self.named_modules()\n        in_sizes = []\n        out_sizes = []\n        input_ = self.model.example_input_array\n\n        if self.model.on_gpu:\n            input_ = input_.cuda(0)\n\n        if self.model.trainer.use_amp:\n            input_ = input_.half()\n\n        with torch.no_grad():\n\n            for _, m in mods:\n                if type(input_) is list or type(input_) is tuple:  # pragma: no cover\n                    out = m(*input_)\n                else:\n                    out = m(input_)\n\n                if type(input_) is tuple or type(input_) is list:  # pragma: no cover\n                    in_size = []\n                    for x in input_:\n                        if type(x) is list:\n                            in_size.append(len(x))\n                        else:\n                            in_size.append(x.size())\n                else:\n                    in_size = np.array(input_.size())\n\n                in_sizes.append(in_size)\n\n                if type(out) is tuple or type(out) is list:  # pragma: no cover\n                    out_size = np.asarray([x.size() for x in out])\n                else:\n                    out_size = np.array(out.size())\n\n                out_sizes.append(out_size)\n                input_ = out\n\n        self.in_sizes = in_sizes\n        self.out_sizes = out_sizes\n        assert len(in_sizes) == len(out_sizes)\n        return\n\n    def get_layer_names(self):\n        '''Collect Layer Names'''\n        mods = self.named_modules()\n        names = []\n        layers = []\n        for name, m in mods:\n            names += [name]\n            layers += [str(m.__class__)]\n\n        layer_types = [x.split('.')[-1][:-2] for x in layers]\n\n        self.layer_names = names\n        self.layer_types = layer_types\n        return\n\n    def get_parameter_sizes(self):\n        '''Get sizes of all parameters in `model`'''\n        mods = self.named_modules()\n        sizes = []\n        for _, m in mods:\n            p = list(m.parameters())\n            modsz = []\n            for j in range(len(p)):\n                modsz.append(np.array(p[j].size()))\n            sizes.append(modsz)\n\n        self.param_sizes = sizes\n        return\n\n    def get_parameter_nums(self):\n        '''Get number of parameters in each layer'''\n        param_nums = []\n        for mod in self.param_sizes:\n            all_params = 0\n            for p in mod:\n                all_params += np.prod(p)\n            param_nums.append(all_params)\n        self.param_nums = param_nums\n        return\n\n    def make_summary(self):\n        '''\n        Makes a summary listing with:\n\n        Layer Name, Layer Type, Input Size, Output Size, Number of Parameters\n        '''\n\n        cols = ['Name', 'Type', 'Params']\n        if self.model.example_input_array is not None:\n            cols.extend(['In_sizes', 'Out_sizes'])\n\n        df = pd.DataFrame(np.zeros((len(self.layer_names), len(cols))))\n        df.columns = cols\n\n        df['Name'] = self.layer_names\n        df['Type'] = self.layer_types\n        df['Params'] = self.param_nums\n        df['Params'] = df['Params'].map(get_human_readable_count)\n\n        if self.model.example_input_array is not None:\n            df['In_sizes'] = self.in_sizes\n            df['Out_sizes'] = self.out_sizes\n\n        self.summary = df\n        return\n\n    def summarize(self):\n        self.get_layer_names()\n        self.get_parameter_sizes()\n        self.get_parameter_nums()\n\n        if self.model.example_input_array is not None:\n            self.get_variable_sizes()\n        self.make_summary()\n\n\ndef print_mem_stack():  # pragma: no cover\n    for obj in gc.get_objects():\n        try:\n            if torch.is_tensor(obj) or (hasattr(obj, 'data') and torch.is_tensor(obj.data)):\n                logging.info(type(obj), obj.size())\n        except Exception:\n            pass\n\n\ndef count_mem_items():  # pragma: no cover\n    num_params = 0\n    num_tensors = 0\n    for obj in gc.get_objects():\n        try:\n            if torch.is_tensor(obj) or (hasattr(obj, 'data') and torch.is_tensor(obj.data)):\n                obj_type = str(type(obj))\n                if 'parameter' in obj_type:\n                    num_params += 1\n                else:\n                    num_tensors += 1\n        except Exception:\n            pass\n\n    return num_params, num_tensors\n\n\ndef get_memory_profile(mode):\n    \"\"\"\n    'all' means return memory for all gpus\n    'min_max' means return memory for max and min\n    :param mode:\n    :return:\n    \"\"\"\n    memory_map = get_gpu_memory_map()\n\n    if mode == 'min_max':\n        min_index, min_memory = min(memory_map.items(), key=lambda item: item[1])\n        max_index, max_memory = max(memory_map.items(), key=lambda item: item[1])\n\n        memory_map = {min_index: min_memory, max_index: max_memory}\n\n    return memory_map\n\n\ndef get_gpu_memory_map():\n    \"\"\"Get the current gpu usage.\n\n    Returns\n    -------\n    usage: dict\n        Keys are device ids as integers.\n        Values are memory usage as integers in MB.\n    \"\"\"\n    result = subprocess.run(\n        [\n            'nvidia-smi',\n            '--query-gpu=memory.used',\n            '--format=csv,nounits,noheader',\n        ],\n        encoding='utf-8',\n        capture_output=True,\n        check=True)\n    # Convert lines into a dictionary\n    gpu_memory = [int(x) for x in result.stdout.strip().split(os.linesep)]\n    gpu_memory_map = {f'gpu_{index}': memory for index, memory in enumerate(gpu_memory)}\n    return gpu_memory_map\n\n\ndef get_human_readable_count(number):\n    \"\"\"\n    Abbreviates an integer number with K, M, B, T for thousands, millions,\n    billions and trillions, respectively.\n    Examples:\n        123     -> 123\n        1234    -> 1 K       (one thousand)\n        2e6     -> 2 M       (two million)\n        3e9     -> 3 B       (three billion)\n        4e12    -> 4 T       (four trillion)\n        5e15    -> 5,000 T\n    :param number: a positive integer number\n    :returns a string formatted according to the pattern described above.\n    \"\"\"\n    assert number >= 0\n    labels = [' ', 'K', 'M', 'B', 'T']\n    num_digits = int(np.floor(np.log10(number)) + 1 if number > 0 else 1)\n    num_groups = int(np.ceil(num_digits / 3))\n    num_groups = min(num_groups, len(labels))  # don't abbreviate beyond trillions\n    shift = -3 * (num_groups - 1)\n    number = number * (10 ** shift)\n    index = num_groups - 1\n    return f'{int(number):,d} {labels[index]}'\n", "path": "pytorch_lightning/core/memory.py"}], "after_files": [{"content": "'''\nGenerates a summary of a model's layers and dimensionality\n'''\n\nimport gc\nimport os\nimport subprocess\n\nimport numpy as np\nimport pandas as pd\nimport torch\nimport logging\n\n\nclass ModelSummary(object):\n\n    def __init__(self, model, mode='full'):\n        '''\n        Generates summaries of model layers and dimensions.\n        '''\n        self.model = model\n        self.mode = mode\n        self.in_sizes = []\n        self.out_sizes = []\n\n        self.summarize()\n\n    def __str__(self):\n        return self.summary.__str__()\n\n    def __repr__(self):\n        return self.summary.__str__()\n\n    def named_modules(self):\n        if self.mode == 'full':\n            mods = self.model.named_modules()\n            mods = list(mods)[1:]  # do not include root module (LightningModule)\n        elif self.mode == 'top':\n            # the children are the top-level modules\n            mods = self.model.named_children()\n        else:\n            mods = []\n        return list(mods)\n\n    def get_variable_sizes(self):\n        '''Run sample input through each layer to get output sizes'''\n        mods = self.named_modules()\n        in_sizes = []\n        out_sizes = []\n        input_ = self.model.example_input_array\n\n        if self.model.on_gpu:\n            device = next(self.model.parameters()).get_device()\n            # test if input is a list or a tuple\n            if isinstance(input_, (list, tuple)):\n                input_ = [input_i.cuda(device) if torch.is_tensor(input_i) else input_i\n                          for input_i in input_]\n            else:\n                input_ = input_.cuda(device)\n\n        if self.model.trainer.use_amp:\n            # test if it is not a list or a tuple\n            if isinstance(input_, (list, tuple)):\n                input_ = [input_i.half() if torch.is_tensor(input_i) else input_i\n                          for input_i in input_]\n            else:\n                input_ = input_.half()\n\n        with torch.no_grad():\n\n            for _, m in mods:\n                if isinstance(input_, (list, tuple)):  # pragma: no cover\n                    out = m(*input_)\n                else:\n                    out = m(input_)\n\n                if isinstance(input_, (list, tuple)):  # pragma: no cover\n                    in_size = []\n                    for x in input_:\n                        if type(x) is list:\n                            in_size.append(len(x))\n                        else:\n                            in_size.append(x.size())\n                else:\n                    in_size = np.array(input_.size())\n\n                in_sizes.append(in_size)\n\n                if isinstance(out, (list, tuple)):  # pragma: no cover\n                    out_size = np.asarray([x.size() for x in out])\n                else:\n                    out_size = np.array(out.size())\n\n                out_sizes.append(out_size)\n                input_ = out\n\n        self.in_sizes = in_sizes\n        self.out_sizes = out_sizes\n        assert len(in_sizes) == len(out_sizes)\n        return\n\n    def get_layer_names(self):\n        '''Collect Layer Names'''\n        mods = self.named_modules()\n        names = []\n        layers = []\n        for name, m in mods:\n            names += [name]\n            layers += [str(m.__class__)]\n\n        layer_types = [x.split('.')[-1][:-2] for x in layers]\n\n        self.layer_names = names\n        self.layer_types = layer_types\n        return\n\n    def get_parameter_sizes(self):\n        '''Get sizes of all parameters in `model`'''\n        mods = self.named_modules()\n        sizes = []\n        for _, m in mods:\n            p = list(m.parameters())\n            modsz = []\n            for j in range(len(p)):\n                modsz.append(np.array(p[j].size()))\n            sizes.append(modsz)\n\n        self.param_sizes = sizes\n        return\n\n    def get_parameter_nums(self):\n        '''Get number of parameters in each layer'''\n        param_nums = []\n        for mod in self.param_sizes:\n            all_params = 0\n            for p in mod:\n                all_params += np.prod(p)\n            param_nums.append(all_params)\n        self.param_nums = param_nums\n        return\n\n    def make_summary(self):\n        '''\n        Makes a summary listing with:\n\n        Layer Name, Layer Type, Input Size, Output Size, Number of Parameters\n        '''\n\n        cols = ['Name', 'Type', 'Params']\n        if self.model.example_input_array is not None:\n            cols.extend(['In_sizes', 'Out_sizes'])\n\n        df = pd.DataFrame(np.zeros((len(self.layer_names), len(cols))))\n        df.columns = cols\n\n        df['Name'] = self.layer_names\n        df['Type'] = self.layer_types\n        df['Params'] = self.param_nums\n        df['Params'] = df['Params'].map(get_human_readable_count)\n\n        if self.model.example_input_array is not None:\n            df['In_sizes'] = self.in_sizes\n            df['Out_sizes'] = self.out_sizes\n\n        self.summary = df\n        return\n\n    def summarize(self):\n        self.get_layer_names()\n        self.get_parameter_sizes()\n        self.get_parameter_nums()\n\n        if self.model.example_input_array is not None:\n            self.get_variable_sizes()\n        self.make_summary()\n\n\ndef print_mem_stack():  # pragma: no cover\n    for obj in gc.get_objects():\n        try:\n            if torch.is_tensor(obj) or (hasattr(obj, 'data') and torch.is_tensor(obj.data)):\n                logging.info(type(obj), obj.size())\n        except Exception:\n            pass\n\n\ndef count_mem_items():  # pragma: no cover\n    num_params = 0\n    num_tensors = 0\n    for obj in gc.get_objects():\n        try:\n            if torch.is_tensor(obj) or (hasattr(obj, 'data') and torch.is_tensor(obj.data)):\n                obj_type = str(type(obj))\n                if 'parameter' in obj_type:\n                    num_params += 1\n                else:\n                    num_tensors += 1\n        except Exception:\n            pass\n\n    return num_params, num_tensors\n\n\ndef get_memory_profile(mode):\n    \"\"\"\n    'all' means return memory for all gpus\n    'min_max' means return memory for max and min\n    :param mode:\n    :return:\n    \"\"\"\n    memory_map = get_gpu_memory_map()\n\n    if mode == 'min_max':\n        min_index, min_memory = min(memory_map.items(), key=lambda item: item[1])\n        max_index, max_memory = max(memory_map.items(), key=lambda item: item[1])\n\n        memory_map = {min_index: min_memory, max_index: max_memory}\n\n    return memory_map\n\n\ndef get_gpu_memory_map():\n    \"\"\"Get the current gpu usage.\n\n    Returns\n    -------\n    usage: dict\n        Keys are device ids as integers.\n        Values are memory usage as integers in MB.\n    \"\"\"\n    result = subprocess.run(\n        [\n            'nvidia-smi',\n            '--query-gpu=memory.used',\n            '--format=csv,nounits,noheader',\n        ],\n        encoding='utf-8',\n        capture_output=True,\n        check=True)\n    # Convert lines into a dictionary\n    gpu_memory = [int(x) for x in result.stdout.strip().split(os.linesep)]\n    gpu_memory_map = {f'gpu_{index}': memory for index, memory in enumerate(gpu_memory)}\n    return gpu_memory_map\n\n\ndef get_human_readable_count(number):\n    \"\"\"\n    Abbreviates an integer number with K, M, B, T for thousands, millions,\n    billions and trillions, respectively.\n    Examples:\n        123     -> 123\n        1234    -> 1 K       (one thousand)\n        2e6     -> 2 M       (two million)\n        3e9     -> 3 B       (three billion)\n        4e12    -> 4 T       (four trillion)\n        5e15    -> 5,000 T\n    :param number: a positive integer number\n    :returns a string formatted according to the pattern described above.\n    \"\"\"\n    assert number >= 0\n    labels = [' ', 'K', 'M', 'B', 'T']\n    num_digits = int(np.floor(np.log10(number)) + 1 if number > 0 else 1)\n    num_groups = int(np.ceil(num_digits / 3))\n    num_groups = min(num_groups, len(labels))  # don't abbreviate beyond trillions\n    shift = -3 * (num_groups - 1)\n    number = number * (10 ** shift)\n    index = num_groups - 1\n    return f'{int(number):,d} {labels[index]}'\n", "path": "pytorch_lightning/core/memory.py"}]}