forked from huawei/mindspore2022
140 lines
4.6 KiB
C++
140 lines
4.6 KiB
C++
/**
|
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
|
*
|
|
* 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 "runtime/device/bucket.h"
|
|
|
|
#include <memory>
|
|
#include "runtime/device/kernel_runtime_manager.h"
|
|
#include "frontend/parallel/context.h"
|
|
#include "utils/profile.h"
|
|
|
|
namespace mindspore::device {
|
|
void Bucket::AddGradTensor(const tensor::TensorPtr &tensor) {
|
|
if (grad_tensor_list_.size() >= bucket_size_) {
|
|
MS_LOG(EXCEPTION) << "bucket is full";
|
|
}
|
|
grad_tensor_list_.emplace_back(tensor);
|
|
if (grad_tensor_list_.size() > bucket_size_) {
|
|
MS_LOG(EXCEPTION) << "too many tensor add to the bucket, bucket_size_:" << bucket_size_
|
|
<< " total tensor size:" << grad_tensor_list_.size();
|
|
}
|
|
MS_LOG(INFO) << "current bucket tensors size:" << grad_tensor_list_.size();
|
|
// bucket is full, start to launch allreduce
|
|
if (grad_tensor_list_.size() == bucket_size_) {
|
|
full_ = true;
|
|
}
|
|
}
|
|
|
|
void Bucket::Launch() {
|
|
auto start = GetTime();
|
|
if (grad_tensor_list_.size() != bucket_size_) {
|
|
MS_LOG(EXCEPTION) << "Bucket is not full, grad_tensor_list_ size:" << grad_tensor_list_.size()
|
|
<< " bucket_size_:" << bucket_size_;
|
|
}
|
|
MS_LOG(INFO) << "Bucket is full, start to launch AllReduce";
|
|
MS_EXCEPTION_IF_NULL(pre_event_);
|
|
MS_EXCEPTION_IF_NULL(post_event_);
|
|
AllocateAllReduceAddr();
|
|
CopyTensorToContiguousMemory();
|
|
pre_event_->RecordEvent();
|
|
pre_event_->WaitEvent();
|
|
LaunchAllReduce();
|
|
// mul fusion
|
|
CalculateMean();
|
|
post_event_->RecordEvent();
|
|
UpdateTensorAddr();
|
|
// pass event to the tensor
|
|
for (auto &tensor : grad_tensor_list_) {
|
|
MS_EXCEPTION_IF_NULL(tensor);
|
|
tensor->SetDeviceEvent(post_event_);
|
|
}
|
|
MS_LOG(INFO) << "Bucket launch cost:" << (GetTime() - start) * 1e6 << " us";
|
|
}
|
|
|
|
void Bucket::UpdateTensorAddr() {
|
|
if (grad_tensor_list_.size() != bucket_size_ || new_tensor_output_addrs_.size() != bucket_size_) {
|
|
MS_LOG(EXCEPTION) << "grad_tensor_list size:" << grad_tensor_list_.size()
|
|
<< " tensor output addr size:" << new_tensor_output_addrs_.size()
|
|
<< " bucket size:" << bucket_size_;
|
|
}
|
|
|
|
for (size_t i = 0; i < bucket_size_; ++i) {
|
|
auto &tensor = grad_tensor_list_[i];
|
|
MS_EXCEPTION_IF_NULL(tensor);
|
|
auto device_address = std::dynamic_pointer_cast<DeviceAddress>(tensor->device_address());
|
|
// release old addr and manage addr by this Bucket.
|
|
MS_EXCEPTION_IF_NULL(device_address);
|
|
auto origin_dev_ptr = device_address->GetMutablePtr();
|
|
tensor_old_addr_list_.emplace_back(origin_dev_ptr);
|
|
device_address->from_mem_pool_ = false;
|
|
device_address->set_ptr(new_tensor_output_addrs_[i]);
|
|
}
|
|
}
|
|
|
|
void Bucket::CalculateMean() {
|
|
auto parallel_context = parallel::ParallelContext::GetInstance();
|
|
MS_EXCEPTION_IF_NULL(parallel_context);
|
|
auto grad_mean = parallel_context->gradients_mean();
|
|
if (!grad_mean) {
|
|
UpdateTensorOutputAddr(ar_output_addr_);
|
|
return;
|
|
}
|
|
if (launch_mul_ == nullptr) {
|
|
launch_mul_ = CreateLaunchMul();
|
|
MS_EXCEPTION_IF_NULL(launch_mul_);
|
|
}
|
|
// set mul input1 addr
|
|
launch_mul_->SetInputAddr(ar_output_addr_);
|
|
// launch mean
|
|
launch_mul_->LaunchOpKernel();
|
|
// store tensor output addr
|
|
auto launch_output = launch_mul_->GetKernelOutputAddr();
|
|
if (launch_output.size() != 1) {
|
|
MS_LOG(EXCEPTION) << "launch mul outputs should have one output";
|
|
}
|
|
UpdateTensorOutputAddr(launch_output[0]);
|
|
}
|
|
|
|
void Bucket::UpdateTensorOutputAddr(uint8_t *addr) {
|
|
uint8_t *tensor_output = addr;
|
|
for (size_t i = 0; i < bucket_size_; ++i) {
|
|
(void)new_tensor_output_addrs_.emplace_back(tensor_output);
|
|
tensor_output += align_size_list_[i];
|
|
}
|
|
}
|
|
|
|
void Bucket::LazyDeleteOldAddr() {
|
|
MS_LOG(INFO) << "Lazy delete old grad address";
|
|
for (auto old_addr : tensor_old_addr_list_) {
|
|
FreeDeviceMem(old_addr);
|
|
}
|
|
tensor_old_addr_list_.clear();
|
|
}
|
|
|
|
void Bucket::Release() {
|
|
MS_LOG(INFO) << "Clear bucket:" << id_;
|
|
grad_tensor_list_.clear();
|
|
align_size_list_.clear();
|
|
new_tensor_output_addrs_.clear();
|
|
memcpy_input_addrs_.clear();
|
|
memcpy_output_addrs_.clear();
|
|
tensor_type_list_.clear();
|
|
LazyDeleteOldAddr();
|
|
FreeAllDeviceMem();
|
|
full_ = false;
|
|
}
|
|
} // namespace mindspore::device
|