Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

summarize total size of model params in bytes #5590

Merged
merged 30 commits into from
Jan 25, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
af8c258
simplified model size calc
kartik4949 Jan 20, 2021
899b122
fix spaces
kartik4949 Jan 20, 2021
91f5964
fix newlines
kartik4949 Jan 20, 2021
2dfe164
minor refactor
kartik4949 Jan 20, 2021
e09160e
Update pytorch_lightning/core/memory.py
kartik4949 Jan 20, 2021
34b7352
make model size property
kartik4949 Jan 20, 2021
027c1a7
fix doctest
kartik4949 Jan 20, 2021
56a47c6
Update pytorch_lightning/core/memory.py
kartik4949 Jan 20, 2021
64fd7d4
remove explicit doctest from file
kartik4949 Jan 20, 2021
5fa17f1
better docs
kartik4949 Jan 20, 2021
fb5882d
model precalculate size 1.0 mbs
kartik4949 Jan 20, 2021
d48a2e8
better comment
kartik4949 Jan 20, 2021
747ca30
Update tests/core/test_memory.py
kartik4949 Jan 21, 2021
aae411d
Update tests/core/test_memory.py
kartik4949 Jan 21, 2021
eda6581
merge _model_size into model_size property itself
kartik4949 Jan 21, 2021
6ce79fe
minor comment fix
kartik4949 Jan 21, 2021
20758ed
Merge branch 'release/1.2-dev' into model_size
kartik4949 Jan 22, 2021
7084d25
add feature to changelog
kartik4949 Jan 22, 2021
66dccdb
Merge branch 'release/1.2-dev' into model_size
mergify[bot] Jan 24, 2021
4a8902c
Merge branch 'release/1.2-dev' into model_size
mergify[bot] Jan 24, 2021
8602baf
Merge branch 'release/1.2-dev' into model_size
mergify[bot] Jan 24, 2021
d112167
added precision test
kartik4949 Jan 24, 2021
f26e888
Added precision test
kartik4949 Jan 24, 2021
a117015
Small refactor
kartik4949 Jan 24, 2021
82c01b0
merge updates
kartik4949 Jan 24, 2021
8639bfc
isort
kartik4949 Jan 24, 2021
1ed41af
minor def name typo
kartik4949 Jan 24, 2021
214035c
remove monkeypath set env as boringmodel wont need any torch hub cache
kartik4949 Jan 24, 2021
e3db80c
Merge branch 'release/1.2-dev' into model_size
mergify[bot] Jan 24, 2021
e6dc2ba
Merge branch 'release/1.2-dev' into model_size
mergify[bot] Jan 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 38 additions & 5 deletions pytorch_lightning/core/memory.py
Expand Up @@ -159,6 +159,7 @@ class ModelSummary(object):
132 K Trainable params
0 Non-trainable params
132 K Total params
0.506 Total estimated model params size (MB)
>>> ModelSummary(model, mode='full') # doctest: +NORMALIZE_WHITESPACE
| Name | Type | Params | In sizes | Out sizes
--------------------------------------------------------------
Expand All @@ -169,6 +170,7 @@ class ModelSummary(object):
132 K Trainable params
0 Non-trainable params
132 K Total params
0.506 Total estimated model params size (MB)
"""

MODE_TOP = "top"
Expand All @@ -180,6 +182,7 @@ def __init__(self, model, mode: str = MODE_DEFAULT):
self._model = model
self._mode = mode
self._layer_summary = self.summarize()
self._precision_megabytes = (self._model.precision / 8.0) / (1024 ** 2.0) # 1 byte -> 8 bits)
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved

@property
def named_modules(self) -> List[Tuple[str, nn.Module]]:
Expand Down Expand Up @@ -213,6 +216,29 @@ def out_sizes(self) -> List:
def param_nums(self) -> List[int]:
return [layer.num_parameters for layer in self._layer_summary.values()]

@property
def total_parameters(self) -> int:
return sum(p.numel() for p in self._model.parameters())

@property
def trainable_parameters(self) -> int:
return sum(p.numel() for p in self._model.parameters() if p.requires_grad)

@property
def model_size(self) -> float:
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved
return self._model_size()
def _model_size(self) -> float:
"""
Estimates total model size i.e total params size in MBs
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved
total params size gives model size in accounting total model params.

NOTE: Currently only Supported total params size.
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved

Returns:
Total estimated model size(MB).
"""
return self.total_parameters * self._precision_megabytes
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved

def summarize(self) -> Dict[str, LayerSummary]:
summary = OrderedDict((name, LayerSummary(module)) for name, module in self.named_modules)
if self._model.example_input_array is not None:
Expand Down Expand Up @@ -259,11 +285,11 @@ def __str__(self):
if self._model.example_input_array is not None:
arrays.append(["In sizes", self.in_sizes])
arrays.append(["Out sizes", self.out_sizes])
total_parameters = self.total_parameters
trainable_parameters = self.trainable_parameters
model_size = self.model_size

trainable_parameters = sum(p.numel() for p in self._model.parameters() if p.requires_grad)
total_parameters = sum(p.numel() for p in self._model.parameters())

return _format_summary_table(total_parameters, trainable_parameters, *arrays)
return _format_summary_table(total_parameters, trainable_parameters, model_size, *arrays)

def __repr__(self):
return str(self)
Expand All @@ -280,7 +306,7 @@ def parse_batch_shape(batch: Any) -> Union[str, List]:
return UNKNOWN_SIZE


def _format_summary_table(total_parameters: int, trainable_parameters: int, *cols) -> str:
def _format_summary_table(total_parameters: int, trainable_parameters: int, model_size: float, *cols) -> str:
"""
Takes in a number of arrays, each specifying a column in
the summary table, and combines them all into one big
Expand Down Expand Up @@ -316,6 +342,8 @@ def _format_summary_table(total_parameters: int, trainable_parameters: int, *col
summary += "Non-trainable params"
summary += "\n" + s.format(get_human_readable_count(total_parameters), 10)
summary += "Total params"
summary += "\n" + s.format(get_formatted_model_size(model_size), 10)
summary += "Total estimated model params size (MB)"

return summary

Expand Down Expand Up @@ -372,6 +400,8 @@ def get_gpu_memory_map() -> Dict[str, int]:
}
return gpu_memory_map

def get_formatted_model_size(total_model_size: float) -> float:
return f"{total_model_size:,.3f}"

def get_human_readable_count(number: int) -> str:
"""
Expand Down Expand Up @@ -411,3 +441,6 @@ def get_human_readable_count(number: int) -> str:
return f"{int(number):,d} {labels[index]}"
else:
return f"{number:,.1f} {labels[index]}"
if __name__ == "__main__":
import doctest
doctest.testmod()
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved
37 changes: 37 additions & 0 deletions tests/core/test_memory.py
Expand Up @@ -33,6 +33,21 @@ def forward(self, *args, **kwargs):
return {'loss': self.parameter.sum()}


class PreCalculatedModel(LightningModule):
""" A module with precalculated total params size in MB. """

def __init__(self):
super().__init__()
self.layer1 = nn.Linear(10, 100)
self.layer2 = nn.Linear(100, 2)
self.pre_calculated_model_size = 0.005

def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
return x
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved


class UnorderedModel(LightningModule):
""" A model in which the layers not defined in order of execution """

Expand Down Expand Up @@ -247,3 +262,25 @@ def forward(self, *args, **kwargs):
model.example_input_array = example_input
summary = model.summarize(mode=mode)
assert summary.in_sizes == [expected_size]

kartik4949 marked this conversation as resolved.
Show resolved Hide resolved
@pytest.mark.parametrize(['mode'], [
pytest.param(ModelSummary.MODE_FULL),
pytest.param(ModelSummary.MODE_TOP),
])
def test_model_size(mode):
""" Test that model size is calculated correctly. """
model = PreCalculatedModel()
summary = model.summarize(mode=mode)
pre_calculated_model_size = torch.tensor(model.pre_calculated_model_size)
model_size = torch.tensor(summary.model_size)
assert torch.isclose(model_size, pre_calculated_model_size, atol=1e-4)
kartik4949 marked this conversation as resolved.
Show resolved Hide resolved

kartik4949 marked this conversation as resolved.
Show resolved Hide resolved
@pytest.mark.parametrize(['mode'], [
pytest.param(ModelSummary.MODE_FULL),
pytest.param(ModelSummary.MODE_TOP),
])
def test_empty_model_size(mode):
""" Test that empty model size is zero. """
model = EmptyModule()
summary = model.summarize(mode=mode)
assert 0.0 == summary.model_size