HDFGroup / h5pyd

h5py distributed - Python client library for HDF Rest API
Other
109 stars 39 forks source link

Implement MultiManager #167

Closed mattjala closed 3 months ago

mattjala commented 4 months ago

High-level MultiManager interface allows users to use multiple threads to perform reads/writes on a collection of (distinct) datasets. Examples of how to use this interface are shown in the TestMultiManager class.

Resolves #166

mattjala commented 4 months ago

Testing results from a benchmark on my local machine, capped to 8 threads to avoid overwhelming HSDS with requests:

Elapsed multi time to read from 12,000,000 elems in 64 datasets = 15.2272
Elapsed serial time to read from 12,000,000 elems in 64 datasets = 12.7379
Elapsed multi time to write to 12,000,000 elems in 64 datasets = 12.1155
Elapsed serial time to write to 12,000,000 elems in 64 datasets = 15.0920

CPU usage in HSDS was only capped out for the SN during the multi write. Other than that, this benchmark isn't CPU-capped (at least running locally). That or the GIL might be why the performance gain is only ~25% for writing, and is actually a performance penalty for reading

Here are some other benchmarks with different numbers of parallel threads:

4 Threads
Elapsed multi time to read from 12000000 elems in 64 datasets = 13.1364
Elapsed serial time to read from 12000000 elems in 64 datasets = 14.3920
Elapsed multi time to write to 12000000 elems in 64 datasets = 19.3822
Elapsed serial time to write to 12000000 elems in 64 datasets = 18.4147

2 Threads
Elapsed multi time to read from 12000000 elems in 64 datasets = 11.3716
Elapsed serial time to read from 12000000 elems in 64 datasets = 14.4107
Elapsed multi time to write to 12000000 elems in 64 datasets = 13.8106
Elapsed serial time to write to 12000000 elems in 64 datasets = 17.8859

1 Thread (Sanity Check)
Elapsed multi time to read from 12000000 elems in 64 datasets = 14.9388
Elapsed serial time to read from 12000000 elems in 64 datasets = 14.8551
Elapsed multi time to write to 12000000 elems in 64 datasets = 19.8820
Elapsed serial time to write to 12000000 elems in 64 datasets = 20.4815
mattjala commented 4 months ago

Here's the pattern of request and responses that HSDS logs during the multi-threaded read and multi-threaded write portions of the benchmark.

It looks like the requests are actually sent out in parallel and received by HSDS simultaneously.

Read:

2024-02-13T15:55:43.982198268Z REQ> GET: /datasets/d-8884e13d-271bc205-378c-a06d7d-87b702/value [/home/test_user1/h5pyd_multi_bm_0]
2024-02-13T15:55:43.996942551Z REQ> GET: /datasets/d-34949e9a-38d088d1-889f-2e8f7a-dec0ff/value [/home/test_user1/h5pyd_multi_bm_1]
2024-02-13T15:55:44.015048380Z REQ> GET: /datasets/d-9ae3a1a1-2a24b85d-57b5-709e25-6ef236/value [/home/test_user1/h5pyd_multi_bm_2]
2024-02-13T15:55:44.019243886Z REQ> GET: /datasets/d-e0a0a633-994fba09-6b5e-5d5e5c-a0c43e/value [/home/test_user1/h5pyd_multi_bm_3]
2024-02-13T15:55:44.022372691Z REQ> GET: /datasets/d-8452c6fd-b044f279-4b22-318cae-e09deb/value [/home/test_user1/h5pyd_multi_bm_4]
2024-02-13T15:55:44.025161112Z REQ> GET: /datasets/d-e6792e41-abb481f1-06dd-b762fa-bba95d/value [/home/test_user1/h5pyd_multi_bm_5]
2024-02-13T15:55:44.063628502Z REQ> GET: /datasets/d-8e8052fc-f0d2731d-fb62-96b675-172138/value [/home/test_user1/h5pyd_multi_bm_6]
2024-02-13T15:55:44.070149892Z REQ> GET: /datasets/d-e6f07868-03539a71-2086-dce617-113a52/value [/home/test_user1/h5pyd_multi_bm_7]
2024-02-13T15:55:44.099195539Z REQ> GET: /datasets/d-e6792e41-abb481f1-06dd-b762fa-bba95d/value [/home/test_user1/h5pyd_multi_bm_5]
2024-02-13T15:55:44.106738654Z REQ> GET: /datasets/d-8e8052fc-f0d2731d-fb62-96b675-172138/value [/home/test_user1/h5pyd_multi_bm_6]
2024-02-13T15:55:46.104316440Z REQ> GET: /datasets/d-e6792e41-abb481f1-06dd-b762fa-bba95d/value [/home/test_user1/h5pyd_multi_bm_5]
2024-02-13T15:55:46.122923599Z REQ> GET: /datasets/d-8e8052fc-f0d2731d-fb62-96b675-172138/value [/home/test_user1/h5pyd_multi_bm_6]
2024-02-13T15:55:46.580387028Z REQ> POST: /datasets [/home/test_user1/h5pyd_multi_bm_0]
2024-02-13T15:55:46.587173911Z  RSP> <201> (Created): /datasets
2024-02-13T15:55:46.589069020Z REQ> GET: /datasets/d-8884e13d-271bc205-c374-ec825e-b99c83 [/home/test_user1/h5pyd_multi_bm_0]
2024-02-13T15:55:46.590649052Z  RSP> <200> (OK): /datasets/d-8884e13d-271bc205-c374-ec825e-b99c83
2024-02-13T15:55:46.617339709Z REQ> PUT: /datasets/d-8884e13d-271bc205-c374-ec825e-b99c83/value [/home/test_user1/h5pyd_multi_bm_0]
2024-02-13T15:55:46.758683749Z  RSP> <200> (OK): /datasets/d-8884e13d-271bc205-c374-ec825e-b99c83/value
2024-02-13T15:55:46.762119165Z REQ> PUT: /groups/g-8884e13d-271bc205-000c-69b5af-934a8d/links/data2 [/home/test_user1/h5pyd_multi_bm_0]
2024-02-13T15:55:46.764401347Z  RSP> <201> (Created): /groups/g-8884e13d-271bc205-000c-69b5af-934a8d/links/data2
2024-02-13T15:55:46.765916135Z REQ> POST: /datasets [/home/test_user1/h5pyd_multi_bm_1]
2024-02-13T15:55:46.770407772Z  RSP> <201> (Created): /datasets
2024-02-13T15:55:46.771707293Z REQ> GET: /datasets/d-34949e9a-38d088d1-d58d-f52f17-9eccbc [/home/test_user1/h5pyd_multi_bm_1]
2024-02-13T15:55:46.772951279Z  RSP> <200> (OK): /datasets/d-34949e9a-38d088d1-d58d-f52f17-9eccbc
2024-02-13T15:55:46.798197320Z REQ> PUT: /datasets/d-34949e9a-38d088d1-d58d-f52f17-9eccbc/value [/home/test_user1/h5pyd_multi_bm_1]
2024-02-13T15:55:46.956205217Z  RSP> <200> (OK): /datasets/d-34949e9a-38d088d1-d58d-f52f17-9eccbc/value
2024-02-13T15:55:46.960866755Z REQ> PUT: /groups/g-34949e9a-38d088d1-bc1c-1612b0-580059/links/data2 [/home/test_user1/h5pyd_multi_bm_1]

...

2024-02-13T15:55:48.057849845Z REQ> POST: /datasets [/home/test_user1/h5pyd_multi_bm_7]
2024-02-13T15:55:48.062317305Z  RSP> <201> (Created): /datasets
2024-02-13T15:55:48.063803640Z REQ> GET: /datasets/d-e6f07868-03539a71-df61-a7b9e5-6daf71 [/home/test_user1/h5pyd_multi_bm_7]
2024-02-13T15:55:48.065122348Z  RSP> <200> (OK): /datasets/d-e6f07868-03539a71-df61-a7b9e5-6daf71
2024-02-13T15:55:48.090902831Z REQ> PUT: /datasets/d-e6f07868-03539a71-df61-a7b9e5-6daf71/value [/home/test_user1/h5pyd_multi_bm_7]
2024-02-13T15:55:48.326779496Z  RSP> <200> (OK): /datasets/d-e6f07868-03539a71-df61-a7b9e5-6daf71/value
2024-02-13T15:55:48.330298491Z REQ> PUT: /groups/g-e6f07868-03539a71-6e78-f0e08b-db12f9/links/data2 [/home/test_user1/h5pyd_multi_bm_7]
2024-02-13T15:55:48.388842212Z  RSP> <201> (Created): /groups/g-e6f07868-03539a71-6e78-f0e08b-db12f9/links/data2

Write:

2024-02-13T15:55:48.636519455Z REQ> PUT: /datasets/d-34949e9a-38d088d1-d58d-f52f17-9eccbc/value [/home/test_user1/h5pyd_multi_bm_1]
2024-02-13T15:55:48.637343756Z REQ> PUT: /datasets/d-8884e13d-271bc205-c374-ec825e-b99c83/value [/home/test_user1/h5pyd_multi_bm_0]
2024-02-13T15:55:48.704390981Z REQ> PUT: /datasets/d-e0a0a633-994fba09-9f2b-2aa7cb-a14d70/value [/home/test_user1/h5pyd_multi_bm_3]
2024-02-13T15:55:48.705379383Z REQ> PUT: /datasets/d-e6f07868-03539a71-df61-a7b9e5-6daf71/value [/home/test_user1/h5pyd_multi_bm_7]
2024-02-13T15:55:48.706051977Z REQ> PUT: /datasets/d-e6792e41-abb481f1-d810-d18b03-6da11b/value [/home/test_user1/h5pyd_multi_bm_5]
2024-02-13T15:55:48.707009791Z REQ> PUT: /datasets/d-8452c6fd-b044f279-b25e-11dd0e-b37768/value [/home/test_user1/h5pyd_multi_bm_4]
2024-02-13T15:55:48.711182473Z REQ> PUT: /datasets/d-9ae3a1a1-2a24b85d-27bb-8c3345-3994bd/value [/home/test_user1/h5pyd_multi_bm_2]
2024-02-13T15:55:48.715455285Z REQ> PUT: /datasets/d-8e8052fc-f0d2731d-8413-323ae8-27c6f9/value [/home/test_user1/h5pyd_multi_bm_6]
2024-02-13T15:55:49.119978296Z  RSP> <200> (OK): /datasets/d-34949e9a-38d088d1-d58d-f52f17-9eccbc/value
2024-02-13T15:55:50.015750840Z  RSP> <200> (OK): /datasets/d-e6792e41-abb481f1-d810-d18b03-6da11b/value
2024-02-13T15:55:50.037142321Z  RSP> <200> (OK): /datasets/d-8452c6fd-b044f279-b25e-11dd0e-b37768/value
2024-02-13T15:55:50.066563349Z  RSP> <200> (OK): /datasets/d-9ae3a1a1-2a24b85d-27bb-8c3345-3994bd/value
2024-02-13T15:55:50.072449376Z  RSP> <200> (OK): /datasets/d-e0a0a633-994fba09-9f2b-2aa7cb-a14d70/value
2024-02-13T15:55:50.077810509Z  RSP> <200> (OK): /datasets/d-8884e13d-271bc205-c374-ec825e-b99c83/value
2024-02-13T15:55:50.097147981Z  RSP> <200> (OK): /datasets/d-e6f07868-03539a71-df61-a7b9e5-6daf71/value
2024-02-13T15:55:50.098420982Z  RSP> <200> (OK): /datasets/d-8e8052fc-f0d2731d-8413-323ae8-27c6f9/value
mattjala commented 4 months ago

h5pyd shares one HttpConn object between everything in a File. The initial tests were between datasets in different files, so they had different HttpConn objects. The new benchmark (included in the PR) tests with datasets in the same File (same HttpConn) and different files (different HttpConn).

The benchmark is reworked to run many trials on somewhat smaller I/O requests for more consistent results.

With max_workers = 16:

Testing with multiple HTTP Connections
Avg multi time to read from 1000000 elems in 64 datasets = 1.9648
Avg serial time to read from 1000000 elems in 64 datasets = 2.4642
Avg multi time to write to 1000000 elems in 64 datasets = 0.8502
Avg serial time to write to 1000000 elems in 64 datasets = 2.3568
Testing random selections with multiple connections
Avg multi time to read from random selections = 0.0674
Avg serial time to read from random selections = 0.0430
Avg multi time to write to random selections = 0.0448
Avg serial time to write to random selections = 0.0482
Testing with shared HTTP connection
Avg multi time to read from 1000000 elems in 64 datasets = 1.9015
Avg serial time to read from 1000000 elems in 64 datasets = 1.9893
Avg multi time to write to 1000000 elems in 64 datasets = 0.8528
Avg serial time to write to 1000000 elems in 64 datasets = 2.0579

With max_workers=4

Testing with multiple HTTP Connections
Avg multi time to read from 1000000 elems in 64 datasets = 1.9973
Avg serial time to read from 1000000 elems in 64 datasets = 2.3848
Avg multi time to write to 1000000 elems in 64 datasets = 1.0000
Avg serial time to write to 1000000 elems in 64 datasets = 2.2197
Testing random selections with multiple connections
Avg multi time to read from random selections = 0.0259
Avg serial time to read from random selections = 0.0773
Avg multi time to write to random selections = 0.0433
Avg serial time to write to random selections = 0.0908
Testing with shared HTTP connection
Avg multi time to read from 1000000 elems in 64 datasets = 2.1160
Avg serial time to read from 1000000 elems in 64 datasets = 2.0212
Avg multi time to write to 1000000 elems in 64 datasets = 0.9373
Avg serial time to write to 1000000 elems in 64 datasets = 2.0816