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
Stream wait #8571
Merged
Merged
Stream wait #8571
Changes from all commits
Commits
Show all changes
134 commits
Select commit
Hold shift + click to select a range
6e8e9c9
ThreadLocalGuard
lixinqi 08e9178
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi f59d17d
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 3eb809a
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 55c163c
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 8aa2e8f
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 7612597
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi de5f971
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 8e86949
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 2ca0707
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 8537b7e
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 55c5160
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi e643eb1
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi eccdfe6
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 043accc
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 97b0eef
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 1591853
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi ba6f2d7
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 5e1a86a
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 1ee004c
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi e853c71
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi c5afe82
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 14226d6
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 754d6a7
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi acb7c98
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 5916848
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 913f6f5
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi fa3867e
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 61bee99
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 7eb2d72
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 9554f41
stream_wait
lixinqi 7557ace
Merge branch 'master' into stream_wait
lixinqi 797974a
Instruction::Prescheduleable
lixinqi e978387
env var ONEFLOW_VM_ENABLE_STREAM_WAIT
lixinqi 5862a95
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 99fa4ad
fix static check error
clackhan 60175fa
Merge branch 'master' into stream_wait
clackhan 29ad00c
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 7297192
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 0a54078
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi cec8a1d
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi b50e236
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 4962c17
Merge branch 'master' into stream_wait
lixinqi b4f9b31
fix conflicts
lixinqi a6c5d07
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi b6b73a2
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 43197bb
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 4453c58
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 582e11f
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi b46e762
Merge branch 'master' into stream_wait
lixinqi d5f032f
enable StreamWait
lixinqi 1b3b6c7
Merge branch 'master' into stream_wait
lixinqi 4001637
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 1dbac7c
merge master
lixinqi 1c6bd69
Merge branch 'stream_wait' of github.com:Oneflow-Inc/oneflow into str…
lixinqi 7fdc675
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi df91ad2
Merge branch 'master' into stream_wait
lixinqi c2a47ac
do not use an object after std::move
lixinqi 1555f70
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 58df59b
Merge branch 'master' into stream_wait
lixinqi cea5d58
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 29fd659
Merge branch 'master' into stream_wait
lixinqi ccbddef
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 2562e16
Merge branch 'master' into stream_wait
lixinqi cc31bd2
refactor Instruction::Done
lixinqi deb692b
Fix typo in oneflow/core/framework/instructions_builder.cpp
daquexian 45208ed
support stream_wait in AccesBlobByCallback
lixinqi c914f2f
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 98e05ef
put flow._C.stream_touch(buffers) into post_forward_hook
lixinqi 6b7885f
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 09489b2
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi ad38490
merge master
lixinqi ee14204
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 4720413
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi c939c3d
merge master
lixinqi 97b697d
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 2cccecb
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 755199c
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 31a5022
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 49ce984
Merge branch 'stream_wait' of github.com:Oneflow-Inc/oneflow into str…
lixinqi f441aa7
merge master
lixinqi c0ef53b
no event query for StreamWait
lixinqi d690538
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 7ed2811
Merge branch 'master' into stream_wait
lixinqi a3a6056
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 2cda60c
Update oneflow/core/framework/instructions_builder.cpp
lixinqi 364911e
Merge branch 'master' into stream_wait
lixinqi eb15c55
auto format by CI
oneflow-ci-bot b4fd1bd
Merge branch 'master' into stream_wait
lixinqi dcaacc6
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi e3161dd
Merge branch 'master' into stream_wait
lixinqi b2aacf5
Merge branch 'master' into stream_wait
mergify[bot] 9c1d602
merge master
lixinqi b1d640c
Merge branch 'stream_wait' of github.com:Oneflow-Inc/oneflow into str…
lixinqi 40e4312
Merge branch 'master' into stream_wait
lixinqi 541e570
Merge branch 'master' into stream_wait
mergify[bot] f6efbb7
include cuda_runtime_api.h
lixinqi a350960
Merge branch 'stream_wait' of github.com:Oneflow-Inc/oneflow into str…
lixinqi 0d37dfa
Merge branch 'master' into stream_wait
mergify[bot] 4d0194d
replace cuda_stream_api.h with cuda_stream.h
lixinqi b3b3a1e
Merge branch 'stream_wait' of github.com:Oneflow-Inc/oneflow into str…
lixinqi 20d591b
using default flags for cudaStreamWaitEvent
lixinqi 700c39a
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 314e037
Merge branch 'master' into stream_wait
lixinqi 1d73197
passing zero to 3rd argument of cudaStreamWaitEvent
lixinqi b6ed0fe
Merge branch 'master' into stream_wait
lixinqi 1c6f65f
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 9247cba
Merge branch 'master' into stream_wait
mergify[bot] b1ae914
Merge branch 'master' into stream_wait
mergify[bot] ef3da78
Merge branch 'master' into stream_wait
mergify[bot] 1d3c62f
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 612b397
merge master
lixinqi 11c2021
fix complier complaints
lixinqi 50bc3ed
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 7af07cf
merge master
lixinqi 486c43a
Merge branch 'master' into stream_wait
lixinqi 3aee226
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 1cf3aba
Merge branch 'master' into stream_wait
lixinqi f44ad7e
Merge branch 'master' into stream_wait
mergify[bot] d540ee0
Merge branch 'master' into stream_wait
lixinqi f828447
Merge branch 'master' into stream_wait
ouyangyu 4de4d3b
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 6f4156e
Merge branch 'master' into stream_wait
lixinqi d5548bc
fix bug in StreamWaitInstructionPolicy::InitInstructionStatus
lixinqi ff27216
Merge branch 'stream_wait' of github.com:Oneflow-Inc/oneflow into str…
lixinqi 3b4dc75
Merge branch 'master' into stream_wait
mergify[bot] 8691ced
Merge branch 'master' into stream_wait
mergify[bot] 8164635
Merge branch 'master' of github.com:Oneflow-Inc/oneflow
lixinqi 627f363
merge master
lixinqi b142ea1
Merge branch 'master' into stream_wait
mergify[bot] a53003e
Merge branch 'master' into stream_wait
lixinqi 3effc13
Merge branch 'master' into stream_wait
ouyangyu f8ad010
Merge branch 'master' into stream_wait
ouyangyu 39527a5
Merge branch 'master' into stream_wait
mergify[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
Copyright 2020 The OneFlow Authors. All rights reserved. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
#ifndef ONEFLOW_CORE_FRAMEWORK_STREAM_SUPPORT_STREAM_WAIT_H_ | ||
#define ONEFLOW_CORE_FRAMEWORK_STREAM_SUPPORT_STREAM_WAIT_H_ | ||
|
||
#include <glog/logging.h> | ||
#include "oneflow/core/common/stream_type.h" | ||
|
||
namespace oneflow { | ||
|
||
struct StreamSupportStreamWait : public StreamTypeVisitor<StreamSupportStreamWait> { | ||
static bool VisitCompute(DeviceType device_type) { return Supported(device_type); } | ||
static bool VisitHost2Device(DeviceType device_type) { return false; } | ||
static bool VisitDevice2Host(DeviceType device_type) { return false; } | ||
static bool VisitAsyncedDevice2Host(DeviceType device_type) { | ||
return VisitDevice2Host(device_type); | ||
} | ||
static bool VisitSyncedLaunchedCommNet(DeviceType device_type) { return Supported(device_type); } | ||
static bool VisitAsyncedLaunchedCommNet(DeviceType device_type) { return Supported(device_type); } | ||
static bool VisitBarrier(DeviceType device_type) { return false; } | ||
static bool VisitCriticalSection(DeviceType device_type) { return false; } | ||
static bool VisitLazyJobLauncher(DeviceType device_type) { return false; } | ||
static bool VisitPinnedCompute(DeviceType device_type) { return VisitCompute(device_type); } | ||
static bool VisitTmpCompute(DeviceType device_type) { return VisitCompute(device_type); } | ||
|
||
private: | ||
static bool Supported(DeviceType device_type) { return device_type == kCUDA; } | ||
}; | ||
|
||
} // namespace oneflow | ||
|
||
#endif // ONEFLOW_CORE_FRAMEWORK_STREAM_SUPPORT_STREAM_WAIT_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
Copyright 2020 The OneFlow Authors. All rights reserved. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
#include "oneflow/core/vm/stream_wait_instruction_policy.h" | ||
#include "oneflow/core/vm/ep_event.h" | ||
#include "oneflow/core/vm/instruction.h" | ||
#include "oneflow/core/vm/stream.h" | ||
#include "oneflow/core/ep/cuda/cuda_event.h" | ||
#include "oneflow/core/ep/cuda/cuda_stream.h" | ||
#include "oneflow/core/ep/cuda/cuda_device.h" | ||
#include "oneflow/core/vm/ep_stream_policy_base.h" | ||
#include "oneflow/core/vm/ep_optional_event_record_status_querier.h" | ||
|
||
namespace oneflow { | ||
namespace vm { | ||
|
||
StreamWaitInstructionPolicy::StreamWaitInstructionPolicy( | ||
small_vector<intrusive::shared_ptr<LocalDepObject>, kOpArgsReservedSize>&& dependences, | ||
vm::Stream* from_vm_stream, vm::Stream* to_vm_stream) | ||
: dependences_(std::move(dependences)), | ||
input_dependences_(), | ||
output_dependences_(), | ||
from_vm_stream_(from_vm_stream) { | ||
for (const auto& dep : dependences_) { output_dependences_.push_back(dep.get()); } | ||
stream_sequential_dependence_ = to_vm_stream->schedule_local_dep_object().get(); | ||
} | ||
|
||
bool StreamWaitInstructionPolicy::Prescheduleable(const Stream* src, const Stream* dst) const { | ||
return &src->thread_ctx() == &dst->thread_ctx(); | ||
} | ||
|
||
void StreamWaitInstructionPolicy::InitInstructionStatus(Instruction* instruction) { | ||
auto* stream = mut_from_vm_stream(); | ||
auto* ep_stream_policy_base = | ||
CHECK_NOTNULL(dynamic_cast<EpStreamPolicyBase*>(instruction->mut_stream_policy())); | ||
ep_stream_policy_base->InitInstructionStatus(*stream, instruction->mut_status_buffer()); | ||
auto* ep_event_provider = ep_stream_policy_base->ep_event_provider(); | ||
const auto& ep_event = CHECK_NOTNULL(ep_event_provider)->GetReusedEpEvent(); | ||
mut_ep_event() = ep_event; | ||
} | ||
|
||
void StreamWaitInstructionPolicy::DeleteInstructionStatus(Instruction* instruction) { | ||
auto* stream = mut_from_vm_stream(); | ||
instruction->stream_policy().DeleteInstructionStatus(*stream, instruction->mut_status_buffer()); | ||
mut_ep_event().reset(); | ||
} | ||
|
||
void StreamWaitInstructionPolicy::Compute(vm::Instruction* instruction) { | ||
const auto& ep_event = mut_ep_event(); | ||
{ | ||
// Record event. | ||
auto* from_naive_stream_policy = | ||
dynamic_cast<EpStreamPolicyBase*>(mut_from_vm_stream()->mut_stream_policy()); | ||
CHECK_NOTNULL(from_naive_stream_policy); | ||
auto* from_stream = from_naive_stream_policy->stream(); | ||
from_stream->RecordEvent(ep_event->mut_event()); | ||
} | ||
{ | ||
// Wait event. | ||
auto* to_ep_stream_policy_base = | ||
dynamic_cast<EpStreamPolicyBase*>(instruction->mut_stream()->mut_stream_policy()); | ||
CHECK_NOTNULL(to_ep_stream_policy_base); | ||
auto* to_ep_stream = to_ep_stream_policy_base->stream(); | ||
CHECK_EQ(ep_event->mut_device(), to_ep_stream->device()) | ||
<< "only support waiting events from same device"; | ||
ep_event->mut_device()->SetAsActiveDevice(); | ||
#ifdef WITH_CUDA | ||
|
||
auto* ep_cuda_event = CHECK_NOTNULL(dynamic_cast<ep::CudaEvent*>(ep_event->mut_event())); | ||
auto* ep_cuda_stream = CHECK_NOTNULL(dynamic_cast<ep::CudaStream*>(to_ep_stream)); | ||
|
||
OF_CUDA_CHECK( | ||
cudaStreamWaitEvent(ep_cuda_stream->cuda_stream(), ep_cuda_event->cuda_event(), 0)); | ||
#else | ||
UNIMPLEMENTED(); | ||
#endif // WITH_CUDA | ||
} | ||
} | ||
|
||
} // namespace vm | ||
} // namespace oneflow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
Copyright 2020 The OneFlow Authors. All rights reserved. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
#ifndef ONEFLOW_CORE_VM_STREAM_WAIT_INSTRUCTION_POLICY_H_ | ||
#define ONEFLOW_CORE_VM_STREAM_WAIT_INSTRUCTION_POLICY_H_ | ||
|
||
#include <functional> | ||
#include "oneflow/core/eager/local_dep_object.h" | ||
#include "oneflow/core/vm/instruction_policy.h" | ||
#include "oneflow/core/common/op_args_reserved_size.h" | ||
#include "oneflow/core/common/small_vector.h" | ||
|
||
namespace oneflow { | ||
class EpEvent; | ||
namespace vm { | ||
|
||
class Stream; | ||
|
||
class StreamWaitInstructionPolicy final : public vm::InstructionPolicy { | ||
public: | ||
StreamWaitInstructionPolicy( | ||
small_vector<intrusive::shared_ptr<LocalDepObject>, kOpArgsReservedSize>&& dependences, | ||
vm::Stream* from_vm_stream, vm::Stream* to_vm_stream); | ||
~StreamWaitInstructionPolicy() = default; | ||
|
||
std::string DebugName(const vm::Instruction&) const override { return "StreamWait"; } | ||
|
||
bool Prescheduleable(const Stream* src, const Stream* dst) const override; | ||
void InitInstructionStatus(Instruction* instruction) override; | ||
void DeleteInstructionStatus(Instruction* instruction) override; | ||
Maybe<void> Prepare(vm::Instruction* instruction) override { return Maybe<void>::Ok(); } | ||
void Compute(vm::Instruction* instruction) override; | ||
|
||
const DependenceVector& input_dependences() const override { return input_dependences_; } | ||
const DependenceVector& output_dependences() const override { return output_dependences_; } | ||
|
||
void ForEachInputEagerBlobObjects(void (*DoEach)(EagerBlobObject*)) const override {} | ||
|
||
private: | ||
vm::Stream* mut_from_vm_stream() { return from_vm_stream_; } | ||
std::shared_ptr<EpEvent>& mut_ep_event() { return ep_event_; } | ||
|
||
small_vector<intrusive::shared_ptr<LocalDepObject>, kOpArgsReservedSize> dependences_; | ||
DependenceVector input_dependences_; | ||
DependenceVector output_dependences_; | ||
vm::Stream* from_vm_stream_; | ||
std::shared_ptr<EpEvent> ep_event_; | ||
}; | ||
|
||
} // namespace vm | ||
} // namespace oneflow | ||
|
||
#endif // ONEFLOW_CORE_VM_STREAM_WAIT_INSTRUCTION_POLICY_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
原来用SoftSyncStream 为何改成 RecordEvent