Skip to content

Adding performance message for Table.read with memmap=True - #9404

Merged
bsipocz merged 6 commits into
astropy:masterfrom
geekypathak21:add-example
Oct 29, 2019
Merged

bsipocz merged 6 commits into
astropy:masterfrom
geekypathak21:add-example

Conversation

@geekypathak21

Copy link
Copy Markdown
Contributor

Description

This pull request is to address ...

Fixes #8573

I added an example in performance docs to show an efficient way to use Table.read().

@astropy-bot astropy-bot Bot added the table label Oct 18, 2019
Comment thread docs/table/performance.inc.rst Resolved
@pllim pllim added the Docs label Oct 18, 2019
@bsipocz bsipocz added this to the v4.0 milestone Oct 18, 2019
@pllim
pllim requested review from cdeil, saimn and taldcroft October 18, 2019 19:11
Comment thread docs/table/performance.inc.rst Resolved
Comment thread docs/table/performance.inc.rst Resolved
@geekypathak21

Copy link
Copy Markdown
Contributor Author

Thanks for suggestions @pllim @bsipocz . I have changed everything as suggested

Comment thread docs/table/performance.inc.rst Outdated

>>> tm.write('tm.ecsv', overwrite=True, serialize_method='data_mask') # doctest: +SKIP

Reading a ``.fits`` in |Table| using

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be Read a large FITS file in ..., and same further down read a large FITS file. For small files using memmap=True will likely degrade performance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The text still refers to reading a .fits, that needs to be FITS file.

Comment thread docs/table/performance.inc.rst Resolved
Comment thread docs/table/performance.inc.rst Resolved
@geekypathak21

Copy link
Copy Markdown
Contributor Author

Thanks, @taldcroft. Everything done as suggested

Comment thread docs/table/performance.inc.rst Resolved
@cdeil

cdeil commented Oct 20, 2019

Copy link
Copy Markdown
Member

@himanshupathak21061998 - Thanks!

From this docs addition, I don't think I would have understood when to use memmap=True and when it's not useful.

@saimn explained the key points in #8573 (comment) and showed examples in https://github.com/saimn/misc-astro/blob/master/astropy/Table_memmap.ipynb

  • FITS data is stored row by row
  • memmap is only useful when reading a row subset
  • reading a single column will read all table data (all rows and columns) into memory

Suggest to reword the explanation and recommendation along those lines.

@geekypathak21

Copy link
Copy Markdown
Contributor Author

@cdeil Should I also include outputs of imu.start_watching_memory() like in the example.

@cdeil

cdeil commented Oct 23, 2019

Copy link
Copy Markdown
Member

@himanshupathak21061998 - My suggestion would be to not include a fully worked example, including how to measure with ipython_memory_usage.

I think a short explanation like this contains all the infos?

Read with memmap=True
--------------------------

By default `Table.read` will read the whole table into memory, which will take a lot of memory and can take a lot of time, depending on the table size and file format. In some cases, it's possibly to only read a subset of the table by choosing the option ``memmap=True``.

For FITS binary tables, the data is stored row by row, and it is possible to read only a subset of rows, but reading a full column load the whole table data into memory.

    # Very fast, doesn't actually load table data into memory
    table = Table.read("table.fits", memmap=True)
    #  Fast, will read only first 100 rows:
    table2 = table[:100]
    print(table2) # accessing column data triggers the read
    # Will load all table data / all columns into memory:
    col = table["my_column"]

TODO: what about HDF5? probably does support memmap? useful for row or column subsets?
TODO: what about ASCII? probably never supports memmap and that's fine?

@geekypathak21

geekypathak21 commented Oct 24, 2019 •

Copy link
Copy Markdown
Contributor Author

@cdeil I think hdf5 also does not support memmap
I have got this error

TypeError: read_table_hdf5() got an unexpected keyword argument 'memmap'

Code to reproduce

import numpy as np
from astropy.table import Table
tbl = Table({ 'a': np.arange(1e7),
             'b': np.arange(1e7, dtype=float),
             'c': np.arange(1e7, dtype=float)})
tbl.write('test.hdf5', overwrite=True)
table1 = Table.read("test.hdf5",memmap=True)

@cdeil cdeil left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@himanshupathak21061998 - A few typos / grammar suggestions inline. Otherwise I'm happy with this now. Thanks!

I'm not sure if the statement on HDF5 is correct. It might always use memmap under the hood. You could try to find out by measuring memory use when reading a row or column subset, or by reading the code. Or others reviewing the PR here like @taldcroft will know for sure.

Comment thread docs/table/performance.inc.rst Outdated
--------------------------

By default :meth:`~astropy.table.Table.read` will read the whole table into memory, which
will take a lot of memory and can take a lot of time, depending on the table size and

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will -> can

Comment thread docs/table/performance.inc.rst Outdated
Length = 100 rows
>>> col = table["my_column"] # Will load all table into memory

Right now :meth:`~astropy.table.Table.read` does not supports ``memmap=True`` for HDF5 and ASCII

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Right now" -> "At the moment"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

supports -> support

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for HDF5 -> for the HDF5

Comment thread docs/table/performance.inc.rst Outdated

>>> tm.write('tm.ecsv', overwrite=True, serialize_method='data_mask') # doctest: +SKIP

Read FILE with memmap=True

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FILE -> FITS

@pllim

pllim commented Oct 24, 2019

Copy link
Copy Markdown
Member

@taldcroft , since you requested changes, can you please give this one another look? Thanks!

@bsipocz
bsipocz requested a review from taldcroft October 24, 2019 20:55
Comment thread docs/table/performance.inc.rst Outdated

By default :meth:`~astropy.table.Table.read` will read the whole table into memory, which
can take a lot of memory and can take a lot of time, depending on the table size and
file format. In some cases, it's possibly to only read a subset of the table by choosing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
file format. In some cases, it's possibly to only read a subset of the table by choosing
file format. In some cases, it's possible to only read a subset of the table by choosing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful to clarify the "In some cases". I think that the table will always be loaded fully in memory if one column must be converted to another format, i.e. when there is a boolean column, or when some column must be scaled.
This is if I remember correctly the discussions on @astrofrog 's PR, so maybe he remembers better than me ;).

Comment thread docs/table/performance.inc.rst Outdated
... 'b': np.arange(1e7, dtype=float),
... 'c': np.arange(1e7, dtype=float)})
>>> tbl.write('test.fits', overwrite=True)
>>> table = Table.read("test.fits", memmap=True) # Very fast, doesn't actually load data

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick but it's better to be consistent with the other lines:

Suggested change
>>> table = Table.read("test.fits", memmap=True) # Very fast, doesn't actually load data
>>> table = Table.read('test.fits', memmap=True) # Very fast, doesn't actually load data

Comment thread docs/table/performance.inc.rst Outdated
98.0 98.0 98.0
99.0 99.0 99.0
Length = 100 rows
>>> col = table["my_column"] # Will load all table into memory

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
>>> col = table["my_column"] # Will load all table into memory
>>> col = table['my_column'] # Will load all table into memory

@taldcroft

Copy link
Copy Markdown
Member

@pllim @saimn - are you happy enough with this now? Seems good enough to me.

@pllim

pllim commented Oct 25, 2019

Copy link
Copy Markdown
Member

I am deferring to @saimn . 😬

@saimn

saimn commented Oct 25, 2019

Copy link
Copy Markdown
Contributor

Yes, looks good to me. Thanks @himanshupathak21061998!

@pllim

pllim commented Oct 25, 2019

Copy link
Copy Markdown
Member

Should let the [docs only] CI run instead of [skip ci] before merge.

@bsipocz

bsipocz commented Oct 25, 2019

Copy link
Copy Markdown
Member

The doctest is skipped, so I would say #yolo and merge this now.

@pllim
pllim requested a review from lglattly October 26, 2019 00:18

@pllim pllim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a commit of nitpicks and triggered the CI. If it passed (I think it should), then this LGTM. Since @taldcroft and @saimn already unofficially approved it, I am going to officially do it here.

But I'll let it stay open a bit more in case @lglattly wants to copy-edit.

@lglattly lglattly left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small copy editing suggestions, looks good to me otherwise!

Comment thread docs/table/performance.inc.rst Resolved
Comment thread docs/table/performance.inc.rst Resolved
@geekypathak21

geekypathak21 commented Oct 29, 2019 •

Copy link
Copy Markdown
Contributor Author

I think tests failures are unrelated to this pr 😕

@bsipocz
bsipocz dismissed taldcroft’s stale review October 29, 2019 18:07

The review has been addressed, and reviewer was happy with the PR in his latest comment.

@bsipocz
bsipocz merged commit 1f4e1b2 into astropy:master Oct 29, 2019
@bsipocz

bsipocz commented Oct 29, 2019

Copy link
Copy Markdown
Member

mpl related CI failures are indeed unrelated, so I'm merging this now given the overall approval above.

Thanks @himanshupathak21061998!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Give example for Table.read with memmap=True

8 participants