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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dense reader: read next batch of tiles as other get processed. #3965

Merged
merged 8 commits into from
Mar 28, 2023

Conversation

KiterLuc
Copy link
Contributor

This change moves tile processing to another task so that the read can continue until another read operation is encountered. The reader then does the read, after which it will wait for the running process operation to complete before kicking off the new one. This will make it so that most reads after the first one come for free. For large queries, rough benchmarking shows that we reduce query time by 30%.


TYPE: IMPROVEMENT
DESC: Dense reader: read next batch of tiles as other get processed.

@KiterLuc KiterLuc requested a review from ihnorton March 13, 2023 15:25
@shortcut-integration
Copy link

This pull request has been linked to Shortcut Story #25396: Read tiles as others get unfiltered..

clear_tiles(name, result_tiles);
compute_task = storage_manager_->compute_tp()->execute(
[&,
filtered_data = std::move(filtered_data),
Copy link
Contributor

Choose a reason for hiding this comment

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

filtered_data doesn't appear to actually be used in here, maybe irrelevant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is used indirectly. The memory that the filtered_data object contains needs to be kept alive until unfiltering is completed, which happens at the end of this task.

test/src/unit-dense-reader.cc Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.cc Outdated Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.cc Outdated Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.cc Outdated Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.cc Outdated Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.cc Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.h Outdated Show resolved Hide resolved
@lums658
Copy link
Contributor

lums658 commented Mar 15, 2023

Editorializing, there is an important general principle here that can be recognized independent of this (or any) particular application, namely overlapping I/O with computation. As long as the same processor (or a single thread) isn't doing both I/O and compute, it is generally a win and is especially useful for hiding latency.

The general pattern is

  • Start an asynchronous I/O operation
  • Do some computational work that does not need the results of the I/O
  • Complete I/O operation
  • Do computational work using the results of I/O

If multiple I/O calls are required, one can do

  • While not done
    • Start an asynchronous I/O operation
    • Do some computational work that does not need the results of the current I/O, but may use results from previous I/O
    • Complete I/O operation
    • Process the results of the just-completed I/O (sometimes this gets wrapped into a single computational step)

The advantage of following this kind of a pattern is that the concurrency between I/O and computation is localized and fairly easy to follow -- structured, in other words. In the PR, it seems like the compute is being made asynchronous and also being passed around so it isn't clear where it is completing or where it is getting launched again. So we should try to figure out a way of making it more structured.

(As an aside, the I/O is usually the thing that is made asynchronous because most operating systems have I/O subsystems that support asynchronous operations. In our situation, the I/O is much more complicated than just doing an OS call.)

(As an aside aside -- we should audit the code to find other overlap opportunities like this -- but also develop a formula to realize the overlap in a more structured way.)

This change moves tile processing to another task so that the read can continue until another read operation is encountered. The reader then does the read, after which it will wait for the running process operation to complete before kicking off the new one. This will make it so that most reads after the first one come for free. For large queries, rough benchmarking shows that we reduce query time by 30%.

---
TYPE: IMPROVEMENT
DESC: Dense reader: read next batch of tiles as other get processed.
@KiterLuc KiterLuc force-pushed the lr/dense-reader-read-copy-parallel/ch25396 branch from f346b4b to 76ff3da Compare March 15, 2023 10:10
Copy link
Contributor

@lums658 lums658 left a comment

Choose a reason for hiding this comment

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

All of my immediate concerns were addressed. There are a few things (the pattern for creating can passing around compute_task) that need to be planned and executed more carefully, but will ansi need to be part of a larger restructuring. I don't think we need to implement those things for this PR as that restructuring will be large task on its own.

tiledb/common/thread_pool/thread_pool.cc Show resolved Hide resolved
test/src/unit-dense-reader.cc Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.cc Show resolved Hide resolved
tiledb/sm/query/readers/dense_reader.cc Outdated Show resolved Hide resolved
}

// Process all tiles in parallel.
auto status = parallel_for_2d(
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to use num_range_threads-1 here to count for the extra compute thread?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The range threads are not actually the number of threads in the threadpool. They are only used when a read will be a few large tiles. At that point, we will split the work for a tile across threads. Also, by the time the work of the parallel for in the compute task gets processed, the compute task should already mostly be in a waiting/yielding state.

tiledb/sm/query/readers/dense_reader.cc Show resolved Hide resolved
@ihnorton ihnorton merged commit 443d233 into dev Mar 28, 2023
@ihnorton ihnorton deleted the lr/dense-reader-read-copy-parallel/ch25396 branch March 28, 2023 14:54
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.

5 participants