- Notifications
You must be signed in to change notification settings - Fork 5.9k
Refine channel test #7946
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
Refine channel test #7946
Conversation
paddle/framework/channel_test.cc Outdated
| framework::ThreadPool* pool; | ||
| pool = framework::ThreadPool::GetInstance(); | ||
| | ||
| // Receiver |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be "Consumer" and "Producer".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
paddle/framework/channel_test.cc Outdated
| CloseChannel(ch); | ||
| } | ||
| | ||
| TEST(Channel, Buffered) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a test case for "unbuffered" channel too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implement of unbuffered channel is empty.
Paddle/paddle/framework/details/unbuffered_channel.h
Lines 41 to 48 in fb1a0df
| template <typename T> | |
| void UnBuffered<T>::Send(T* channel_element) {} | |
| template <typename T> | |
| void UnBuffered<T>::Receive(T*) {} | |
| template <typename T> | |
| UnBuffered<T>::~UnBuffered() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This issue is about unbuffered channel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. LGTM!
paddle/framework/channel_test.cc Outdated
| Channel<int>* ch = MakeChannel<int>(capacity); | ||
| | ||
| framework::ThreadPool* pool; | ||
| pool = framework::ThreadPool::GetInstance(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For two reasons, let us do not use framework::ThreadPool in this unit test, but use std::thread:
- To minimize the dependencies.
framework::ThreadPoolsets the number of OS threads automatically, which could be one.
paddle/framework/channel_test.cc Outdated
| pool = framework::ThreadPool::GetInstance(); | ||
| | ||
| // Consumer | ||
| for (int i = 0; i < capacity; ++i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the purpose of this unit test. Do you have a list of edge cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let us remoe the dependency to ThreadPool
ccf829c to be0525f Compare ae1d0f9 to 3e7ca5c Compare paddle/framework/channel.h Outdated
| } | ||
| | ||
| template <typename T> | ||
| void DeleteChannel(Channel<T>* ch) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that we need CloseChannel, which mimics Go's close, and DeleteChannel, which mimics Go's garbage collection.
One step forward, I think we can have only CloseChannel, because DeleteChannel could be simplified as delete ch -- I didn't have to and should not have defined template <typename T> void DeleteChannel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you.
We should make a further analysis about CloseChannel. When the channel was closed, the channel_ of Channel may also have some data, I think that receive can also work properly, but send cannot send data to channel_.
So, CloseChannel should not delete Buffered or Unbuffered.
If we close the channel by calling the destructor, the objection will be deleted.
But the destructor also calls notify_one, this causes some data also to be placed in the channel, this is obviously an error.
Paddle/paddle/framework/details/buffered_channel.h
Lines 67 to 72 in 311334e
| template <typename T> | |
| Buffered<T>::~Buffered() { | |
| std::unique_lock<std::mutex> lock(mu_); | |
| channel_.clear(); | |
| NotifyAllSenders(&lock); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to close the channel via the destructor. My idea is the other way. See #7946 (comment)
| std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait 0.5 sec | ||
| EXPECT_EQ(sum, 45U); | ||
| CloseChannel(ch); | ||
| t.join(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that you closed but didn't delete the channel in this test? In my mind, this test should look like
std::unique_ptr<Channel<int>*> ch(MakeChannel<int>(10)); // `delete ch.get()` will be called do_something_here_with(ch); CloseChannel(ch.get());There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that you closed but didn't delete the channel in this test?
We can add DeleteChannel behind CloseChannel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maye the use of unique_ptr didn't present my idea clearly. Let us use delete explicitly:
auto ch = MakeChannel<int>(10); do_something(ch); CloseChannel(ch); delete ch;There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok!
If we use delete to destroy the ch but other threads also hold the ch and these threads send data to the ch, there will cause an error.
I wonder that whether this case is existent.
| std::condition_variable empty_cond_var_; | ||
| std::condition_variable full_cond_var_; | ||
| std::deque<T> channel_; | ||
| bool close; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
close => closed_ or closing_
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
efab4f0 to 710e05d Compare 710e05d to 77b8872 Compare 4d6e884 to ba7677e Compare There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Let us merge this PR and go on working on the channels in future PRs.
fix #7948
buffered_channel.buffered_channelunder multithreading.