/** * Copyright 2020 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 "ps/optimizer_info_builder.h" #include #include #include #include "backend/kernel_compiler/cpu/ps/sparse_apply_ftrl_ps_kernel.h" namespace mindspore { namespace ps { using mindspore::kernel::ps::SparseApplyFtrlPSKernel; OptimizerInfo *OptimizerInfoBuilder::Build(const std::shared_ptr &pserver_kernel, const WeightPtr &weight, const Keys &keys, const Values &values, const Lengths &lens, const InputsShapePtr &inputs_shape, size_t worker_num) { MS_EXCEPTION_IF_NULL(pserver_kernel); MS_EXCEPTION_IF_NULL(inputs_shape); OptimizerInfo *optim_info = BuildInputs(weight, keys, values, lens, inputs_shape, worker_num, pserver_kernel); MS_EXCEPTION_IF_NULL(optim_info); std::vector ws_sizes = pserver_kernel->workspace_sizes(); BuildWorkspaces(optim_info, ws_sizes, worker_num); BuildOutputs(optim_info, worker_num); return optim_info; } void OptimizerInfoBuilder::BuildWorkspaces(OptimizerInfo *info, const std::vector &ws_sizes, size_t worker_num) { for (size_t i = 0; i < ws_sizes.size(); i++) { size_t size = ws_sizes[i]; AddressPtr workspace = std::make_shared(); MS_EXCEPTION_IF_NULL(workspace); workspace->addr = new float[size]; MS_EXCEPTION_IF_NULL(workspace->addr); workspace->size = size; info->AddWorkspace(workspace); } } template AddressPtr OptimizerInfoBuilder::GenInputAddrPtr(const std::string &optim_type, const std::string &input_name, void *ps_data, const Lengths &ps_lens, const InputsShapePtr &inputs_shape) { MS_EXCEPTION_IF_NULL(ps_data); // Take note of that the data type maybe inconsistent in ps_data. MS_LOG(INFO) << "Get input address pointer for optimizer:" << optim_type << ", input name:" << input_name; AddressPtr addr_ptr = std::make_shared(); MS_EXCEPTION_IF_NULL(addr_ptr); if (kOptimToOriginIdx.count(optim_type) == 0 || kOptimToPSSendIdx.count(optim_type) == 0) { MS_LOG(EXCEPTION) << "Optimizer type " << optim_type << " in not supported."; } const OptimOriginIdx &origin_input_map = kOptimToOriginIdx.at(optim_type); const OptimPSSendIdx &ps_send_index_map = kOptimToPSSendIdx.at(optim_type); if (ps_send_index_map.count(input_name) == 0 || origin_input_map.count(input_name) == 0) { MS_LOG(EXCEPTION) << "Optimizer " << optim_type << " has no input for " << input_name; } size_t ps_index = ps_send_index_map.at(input_name); if (ps_index == INDEX_NOT_SEND) { MS_LOG(EXCEPTION) << "Input " << input_name << " is not supposed to be sent to PS."; } size_t addr_data_size, addr_data_offset; if (inputs_shape != nullptr) { // addr_data_size should be calculated by inputs_shape if it's passed. size_t origin_index = origin_input_map.at(input_name); EXC_IF_VEC_IDX_OOB((*inputs_shape), origin_index); auto shape = *((*inputs_shape)[origin_index]); addr_data_size = std::accumulate(shape.begin(), shape.end(), worker_num_, std::multiplies()); } else { EXC_IF_VEC_IDX_OOB(ps_lens, ps_index); addr_data_size = ps_lens[ps_index]; } addr_data_offset = std::accumulate(ps_lens.begin(), ps_lens.begin() + ps_index, 0, std::plus()); // The size in ps_lens instead of addr_data_size is the size of real data. T *buffer = new T[addr_data_size]; addr_ptr->size = ps_lens[ps_index] * sizeof(T); addr_ptr->addr = buffer; size_t dst_size = addr_ptr->size; size_t src_size = addr_ptr->size; void *dst_data = addr_ptr->addr; void *src_data = reinterpret_cast(ps_data) + addr_data_offset; MS_EXCEPTION_IF_NULL(dst_data); MS_EXCEPTION_IF_NULL(src_data); int ret = memcpy_s(dst_data, dst_size, src_data, src_size); if (ret != 0) { MS_LOG(EXCEPTION) << "memcpy_s error, errorno(" << ret << ")"; delete[] buffer; buffer = nullptr; return nullptr; } return addr_ptr; } OptimizerInfo *MomentumOptimInfoBuilder::BuildInputs(const WeightPtr &weight, const Keys &keys, const Values &values, const Lengths &lens, const InputsShapePtr &inputs_shape, size_t worker_num, const std::shared_ptr &) { AddressPtr weight_addr = std::make_shared(); MS_EXCEPTION_IF_NULL(weight_addr); weight_addr->addr = weight->data(); weight_addr->size = weight->size() * sizeof(float); AddressPtr accumulate = std::make_shared(); MS_EXCEPTION_IF_NULL(accumulate); accumulate->addr = new float[weight->size()]; MS_EXCEPTION_IF_NULL(accumulate->addr); accumulate->size = weight->size() * sizeof(float); int ret = memset_s(accumulate->addr, accumulate->size, 0x00, accumulate->size); if (ret != 0) { MS_LOG(EXCEPTION) << "memset_s error, errorno(" << ret << ")"; delete[] reinterpret_cast(accumulate->addr); accumulate->addr = nullptr; return nullptr; } AddressPtr learning_rate = GenInputAddrPtr(kApplyMomentum, "lr", values.data(), lens); AddressPtr gradient = GenInputAddrPtr(kApplyMomentum, "grad", values.data(), lens); AddressPtr momentum = GenInputAddrPtr(kApplyMomentum, "momentum", values.data(), lens); return new MomentumOptimInfo(weight_addr, accumulate, learning_rate, gradient, momentum); } OptimizerInfo *SparseAdamOptimInfoBuilder::BuildInputs(const WeightPtr &weight, const Keys &keys, const Values &values, const Lengths &lens, const InputsShapePtr &inputs_shape, size_t worker_num, const std::shared_ptr &) { AddressPtr weight_addr = std::make_shared(); MS_EXCEPTION_IF_NULL(weight_addr); weight_addr->addr = weight->data(); weight_addr->size = weight->size() * sizeof(float); AddressPtr m = std::make_shared(); MS_EXCEPTION_IF_NULL(m); m->addr = new float[weight->size()]; MS_EXCEPTION_IF_NULL(m->addr); m->size = weight->size() * sizeof(float); int ret = memset_s(m->addr, m->size, 0x00, m->size); if (ret != 0) { MS_LOG(EXCEPTION) << "memset_s error, errorno(" << ret << ")"; delete[] reinterpret_cast(m->addr); m->addr = nullptr; return nullptr; } AddressPtr v = std::make_shared(); MS_EXCEPTION_IF_NULL(v); v->addr = new float[weight->size()]; MS_EXCEPTION_IF_NULL(v->addr); v->size = weight->size() * sizeof(float); ret = memset_s(v->addr, v->size, 0x00, v->size); if (ret != 0) { MS_LOG(EXCEPTION) << "memset_s error, errorno(" << ret << ")"; delete[] reinterpret_cast(v->addr); v->addr = nullptr; delete[] reinterpret_cast(m->addr); m->addr = nullptr; return nullptr; } AddressPtr beta1_power = GenInputAddrPtr(kSparseAdam, "beta1_power", values.data(), lens); AddressPtr beta2_power = GenInputAddrPtr(kSparseAdam, "beta2_power", values.data(), lens); AddressPtr learning_rate = GenInputAddrPtr(kSparseAdam, "lr", values.data(), lens); AddressPtr beta1 = GenInputAddrPtr(kSparseAdam, "beta1", values.data(), lens); AddressPtr beta2 = GenInputAddrPtr(kSparseAdam, "beta2", values.data(), lens); AddressPtr epsilon = GenInputAddrPtr(kSparseAdam, "eps", values.data(), lens); AddressPtr grad = GenInputAddrPtr(kSparseAdam, "grad", values.data(), lens, inputs_shape); AddressPtr indices = GenInputAddrPtr(kSparseAdam, "indices", values.data(), lens, inputs_shape); return new SparseAdamOptimInfo(weight_addr, m, v, beta1_power, beta2_power, learning_rate, beta1, beta2, epsilon, grad, indices); } OptimizerInfo *SparseFtrlOptimInfoBuilder::BuildInputs(const WeightPtr &weight, const Keys &keys, const Values &values, const Lengths &lens, const InputsShapePtr &inputs_shape, size_t worker_num, const std::shared_ptr &pserver_kernel) { MS_EXCEPTION_IF_NULL(inputs_shape); AddressPtr weight_addr = std::make_shared(); MS_EXCEPTION_IF_NULL(weight_addr); weight_addr->addr = weight->data(); weight_addr->size = weight->size() * sizeof(float); AddressPtr accum = std::make_shared(); MS_EXCEPTION_IF_NULL(accum); accum->addr = new float[weight->size()]; MS_EXCEPTION_IF_NULL(accum->addr); accum->size = weight->size() * sizeof(float); for (size_t i = 0; i < weight->size(); i++) { float *tmp = reinterpret_cast(accum->addr); tmp[i] = std::dynamic_pointer_cast(pserver_kernel)->init_accum(); } AddressPtr linear = std::make_shared(); MS_EXCEPTION_IF_NULL(linear); linear->addr = new float[weight->size()]; MS_EXCEPTION_IF_NULL(linear->addr); int ret = memset_s(linear->addr, weight->size() * sizeof(float), 0x00, weight->size() * sizeof(float)); if (ret != 0) { MS_LOG(EXCEPTION) << "memset_s error, errorno(" << ret << ")"; delete[] reinterpret_cast(linear->addr); linear->addr = nullptr; return nullptr; } linear->size = weight->size() * sizeof(float); AddressPtr grad = GenInputAddrPtr(kSparseFtrl, "grad", values.data(), lens, inputs_shape); AddressPtr indices = GenInputAddrPtr(kSparseFtrl, "indices", values.data(), lens, inputs_shape); return new SparseFtrlOptimInfo(weight_addr, accum, linear, grad, indices); } } // namespace ps } // namespace mindspore