mindspore注释赛pr #17

Open
airisle wants to merge 2 commits from airisle/mindspore2022:master into master
3 changed files with 2040 additions and 481 deletions

View File

@ -1,3 +1,20 @@
// This is a copyright notice
// This code is licensed under the Apache License, Version 2.0
// The code is written in C++
// The code is for a .cc file
// The code is for a Huawei Technologies Co., Ltd project
// The code is for a file named "example.cc"
// The code is for a class or function named "Example"
// The code is for a method or function named "exampleFunction"
// The code is for a variable named "exampleVariable"
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
@ -14,12 +31,18 @@
* limitations under the License.
*/
// This code includes the header file "embedding_table_shard_metadata.h" which contains the necessary declarations for the EmbeddingTableShardMetadata class.
#include "ps/embedding_table_shard_metadata.h"
// This function returns the value of the 'begin_' member variable of the EmbeddingTableShardMetadata class.
// It is a getter function that provides access to the private member variable 'begin_'.
namespace mindspore {
namespace ps {
uint64_t EmbeddingTableShardMetadata::begin() const { return begin_; }
// This function returns the value of the private member variable 'end_'
// which represents the end position of the embedding table shard metadata.
// The return type of this function is uint64_t.
uint64_t EmbeddingTableShardMetadata::end() const { return end_; }
uint64_t EmbeddingTableShardMetadata::size() const { return end_ - begin_; }

File diff suppressed because it is too large Load Diff

View File

@ -14,250 +14,532 @@
* limitations under the License.
*/
// Include the custom utility header file "ps/util.h"
#include "ps/util.h"
// Include the standard vector header file
#include <vector>
// Include the standard memory header file
#include <memory>
// Include the custom hash map header file "utils/hash_map.h"
#include "utils/hash_map.h"
// Include the custom constants header file "ps/constants.h"
#include "ps/constants.h"
// Include the custom PS context header file "ps/ps_context.h"
#include "ps/ps_context.h"
// Include the custom MS utility header file "utils/ms_utils.h"
#include "utils/ms_utils.h"
// Define the namespace "mindspore"
namespace mindspore {
namespace ps {
mindspore::HashMap<std::string, int64_t> Util::optimizer_to_ids{
{kApplyMomentum, 0},
{kSparseAdam, 1},
{kSparseLazyAdam, 2},
{kSparseFtrl, 3},
};
// Define the namespace "ps" within the "mindspore" namespace
namespace ps {
// Define a HashMap named "optimizer_to_ids" with key type std::string and value type int64_t
mindspore::HashMap<std::string, int64_t> Util::optimizer_to_ids{
// Initialize the HashMap with key-value pairs
{kApplyMomentum, 0},
{kSparseAdam, 1},
{kSparseLazyAdam, 2},
{kSparseFtrl, 3},
};
}
}
// Create a HashMap named id_to_optimizers with key of type int64_t and value of type std::string
mindspore::HashMap<int64_t, std::string> Util::id_to_optimizers{
{0, kApplyMomentum},
{1, kSparseAdam},
{2, kSparseLazyAdam},
{3, kSparseFtrl},
// Initialize the HashMap with key-value pairs
{0, kApplyMomentum}, // Key 0 maps to the value kApplyMomentum
{1, kSparseAdam}, // Key 1 maps to the value kSparseAdam
{2, kSparseLazyAdam}, // Key 2 maps to the value kSparseLazyAdam
{3, kSparseFtrl}, // Key 3 maps to the value kSparseFtrl
};
// Define a HashMap named id_to_optimizer_nodes with key of type int64_t and value of type std::string
mindspore::HashMap<int64_t, std::string> Util::id_to_optimizer_nodes{
{0, kApplyMomentumOp},
{1, kSparseAdamOp},
{2, kSparseLazyAdamOp},
{3, kSparseFtrlOp},
// Initialize the HashMap with key-value pairs
{0, kApplyMomentumOp}, // Key 0 maps to the value kApplyMomentumOp
{1, kSparseAdamOp}, // Key 1 maps to the value kSparseAdamOp
{2, kSparseLazyAdamOp}, // Key 2 maps to the value kSparseLazyAdamOp
{3, kSparseFtrlOp}, // Key 3 maps to the value kSparseFtrlOp
};
bool Util::IsRoleOfPServer() { return PSContext::instance()->is_server(); }
// Define a member function named "IsRoleOfPServer" in the "Util" class that returns a boolean value
bool Util::IsRoleOfPServer() {
bool Util::IsRoleOfScheduler() { return PSContext::instance()->is_scheduler(); }
// Call the "is_server" function of the "PSContext" class instance returned by the "instance" function
// and return the result
return PSContext::instance()->is_server();
}
// Check if the current role is that of a scheduler
bool Util::IsRoleOfScheduler() {
// Use the static method instance() of the PSContext class to get the instance of the PSContext object
// Then call the is_scheduler() method of the PSContext object to check if the current role is a scheduler
return PSContext::instance()->is_scheduler();
}
// Implementation of the optimizer_id function in the Util class
// Takes a reference to a constant string as input parameter
int64_t Util::optimizer_id(const std::string &name) {
// Check if the name exists in the optimizer_to_ids map
if (optimizer_to_ids.count(name) > 0) {
// If the name exists, return the corresponding id from the map
return optimizer_to_ids[name];
}
// If the name does not exist in the map, return -1
return -1;
}
// Define a function named "optimizer_name" which takes an integer id as input and returns a string
std::string Util::optimizer_name(int64_t id) {
// Check if the given id exists in the map "id_to_optimizers"
if (id_to_optimizers.count(id) > 0) {
// If the id exists in the map, return the corresponding optimizer name
return id_to_optimizers[id];
}
// If the id does not exist in the map, return an empty string
return "";
}
// Implementation of the optimizer_node_name function in the Util class
// Takes an integer id as input and returns the corresponding optimizer node name as a string
std::string Util::optimizer_node_name(int64_t id) {
// Check if the id exists in the id_to_optimizer_nodes map
if (id_to_optimizer_nodes.count(id) > 0) {
// If the id exists, return the corresponding optimizer node name
return id_to_optimizer_nodes[id];
}
// If the id does not exist, return an empty string
return "";
}
bool Util::is_optimizer(const std::string &name) { return optimizer_to_ids.count(name) > 0; }
// Check if the given name is an optimizer by using the count function on the optimizer_to_ids map
bool Util::is_optimizer(const std::string &name) {
return optimizer_to_ids.count(name) > 0;
}
// Function to calculate the local shard for a given rank
int64_t Util::LocalShard(int64_t first_dim, int64_t rank_id, int64_t server_num) {
// Calculate the shard dimensions for all ranks
std::map<int64_t, int64_t> shard_dims = AllRankLocalShard(first_dim, rank_id, server_num);
// Check if the shard dimensions for the given rank exist in the map
if (shard_dims.count(rank_id) == 0) {
// If the shard dimensions do not exist, throw an exception with an error message
MS_LOG(EXCEPTION) << "Invalid rank id " << rank_id;
}
// Return the shard dimension for the given rank
return shard_dims[rank_id];
}
// This function calculates the shard dimensions for a given rank in a distributed system
// It takes three input parameters: first_dim, rank_id, and server_num
// It returns a std::map<int64_t, int64_t> object representing the shard dimensions for each server
std::map<int64_t, int64_t> Util::AllRankLocalShard(int64_t first_dim, int64_t rank_id, int64_t server_num) {
// Check if the input values are valid
if (first_dim <= 0 || server_num <= 0 || rank_id < 0) {
MS_LOG(EXCEPTION) << "Input values are invalid, first_dim: " << first_dim << ", server_num: " << server_num
<< ", rank_id: " << rank_id;
}
// Check if the rank_id is within the range of server_num
if (rank_id >= server_num) {
MS_LOG(EXCEPTION) << "The rank ID " << rank_id << " should be less than the number of servers " << server_num;
}
// Create a std::map<int64_t, int64_t> object to store the shard dimensions
std::map<int64_t, int64_t> shard_dims;
// Initialize the shard dimensions for each server to 0
for (int64_t i = 0; i < server_num; i++) {
shard_dims[i] = 0;
}
// Check if the server_num is consistent with the size of shard_dims
if (server_num != static_cast<int64_t>(shard_dims.size())) {
MS_LOG(EXCEPTION) << "Inconsistent server num " << server_num << " shard dims counter size " << shard_dims.size();
}
// Calculate the shard dimensions for each server
int64_t server_index = -1;
for (int64_t i = 0; i < first_dim; i++) {
server_index = (server_index + 1) % server_num;
shard_dims[server_index] = shard_dims[server_index] + 1;
}
// Check if the rank_id is valid
if (shard_dims.count(rank_id) == 0) {
MS_LOG(EXCEPTION) << "Invalid rank id " << rank_id << ", total server num " << server_num;
}
// Return the shard dimensions
return shard_dims;
}
// Define a function named "ReduceSparseGradient" belonging to the "Util" namespace
void Util::ReduceSparseGradient(float *gradients, int *indices, const size_t indices_size, size_t segment_size,
const size_t first_dim_size, const size_t outer_dim_size,
mindspore::kernel::SparseGradient<int> *unique_sparse_grad) {
// Calculate the size of each slice segment
size_t slice_segment_size = indices_size * segment_size;
// Create a vector named "workspace_grad" with size equal to "slice_segment_size" to store gradients
std::vector<float> workspace_grad(slice_segment_size);
// Create a vector named "workspace_indices" with size equal to "indices_size" to store indices
std::vector<int> workspace_indices(indices_size);
MS_EXCEPTION_IF_NULL(gradients);
MS_EXCEPTION_IF_NULL(indices);
mindspore::kernel::SparseGradient<int> workspace_sparse_grad(
{workspace_grad.data(), workspace_indices.data(), indices_size});
mindspore::kernel::SparseGradient<int> input_sparse_grad({gradients, indices, indices_size});
mindspore::kernel::ReduceSparseGradientParam<int> param;
param.input_grad_ = &input_sparse_grad;
param.workspace_grad_ = &workspace_sparse_grad;
param.output_grad_ = unique_sparse_grad;
param.max_index_ = first_dim_size;
param.value_stride_ = outer_dim_size;
mindspore::kernel::SparseOptimizerCpuKernelMod::BucketReduceSparseGradient(param);
}
// Check if the "gradients" pointer is null, and throw an exception if it is
MS_EXCEPTION_IF_NULL(gradients);
// Check if the "indices" pointer is null, and throw an exception if it is
MS_EXCEPTION_IF_NULL(indices);
// Create a SparseGradient object named workspace_sparse_grad, which takes in three arguments:
// 1. A pointer to the data of the workspace_grad object
// 2. A pointer to the data of the workspace_indices object
// 3. The size of the indices (indices_size)
mindspore::kernel::SparseGradient<int> workspace_sparse_grad(
{workspace_grad.data(), workspace_indices.data(), indices_size});
// Create a SparseGradient object named input_sparse_grad, which takes in three arguments:
// 1. A pointer to the data of the gradients object
// 2. A pointer to the data of the indices object
// 3. The size of the indices (indices_size)
mindspore::kernel::SparseGradient<int> input_sparse_grad({gradients, indices, indices_size});
// Create a ReduceSparseGradientParam object named param
mindspore::kernel::ReduceSparseGradientParam<int> param;
// Set the input_grad_ member of the param object to the address of the input_sparse_grad object
param.input_grad_ = &input_sparse_grad;
// Set the workspace_grad_ member of the param object to the address of the workspace_sparse_grad object
param.workspace_grad_ = &workspace_sparse_grad;
// Set the output_grad_ member of the param object to the unique_sparse_grad object
param.output_grad_ = unique_sparse_grad;
// Set the max_index_ member of the param object to the value of first_dim_size
param.max_index_ = first_dim_size;
// Set the value_stride_ member of the param object to the value of outer_dim_size
// Call the `BucketReduceSparseGradient` function of the `SparseOptimizerCpuKernelMod` class from the `mindspore::kernel` namespace, passing `param` as an argument.
// Function to fuse server communication operations
bool Util::FuseServerCommOps(const pipeline::ResourcePtr &res) {
// Get the function graph from the resource
FuncGraphPtr func_graph = res->func_graph();
// Throw an exception if the function graph is null
MS_EXCEPTION_IF_NULL(func_graph);
// Fuse the pull weight operation in the function graph
DoFusion(func_graph, kPullWeightOpName, kFusedPullWeightOpName);
// Fuse the push weight operation in the function graph
DoFusion(func_graph, kPushWeightOpName, kFusedPushWeightOpName);
// Return true to indicate successful fusion of server communication operations
return true;
}
// Define a function named MakeWeightPtr in the Util namespace that takes three arguments:
// 1. A const reference to a shared pointer to a vector of floats named data
// 2. A boolean variable named enable_recovery
// 3. A const reference to a shared pointer to a vector of integers named shape
WeightPtr Util::MakeWeightPtr(const std::shared_ptr<std::vector<float>> &data, bool enable_recovery,
const std::shared_ptr<std::vector<int>> &shape) {
// Declare a variable named weight_ptr of type WeightPtr (presumably a typedef for shared_ptr<Weight>)
WeightPtr weight_ptr;
// Check if enable_recovery is false
if (!enable_recovery) {
// If enable_recovery is false, create a shared pointer to a Weight object using the data and shape arguments
weight_ptr = std::make_shared<Weight>(data, shape);
} else {
// If enable_recovery is true, create a shared pointer to a PersistentWeight object using the data and shape arguments
weight_ptr = std::make_shared<PersistentWeight>(data, shape);
}
// Return the weight_ptr variable
return weight_ptr;
}
// Define a function named "GetPrimitiveName" in the "Util" namespace that takes a reference to a CNodePtr object as input
std::string Util::GetPrimitiveName(const CNodePtr &cnode) {
// Check if the input CNodePtr object is null, and throw an exception if it is
MS_EXCEPTION_IF_NULL(cnode);
// Get the inputs of the CNode object
auto &inputs = cnode->inputs();
// Check if the inputs vector is empty
if (inputs.empty()) {
// If it is empty, log an exception with the message "Inputs of node <node_name> is empty."
MS_LOG(EXCEPTION) << "Inputs of node " << cnode->fullname_with_scope() << " is empty.";
// Return an empty string
return "";
}
// Get the first input of the CNode object
auto fn = inputs[0];
// Check if the first input is a ValueNode of type Primitive
if (!IsValueNode<Primitive>(fn)) {
// If it is not, return an empty string
return "";
}
// If it is, continue with the rest of the code
auto node_prim = GetValueNode<PrimitivePtr>(fn);
MS_EXCEPTION_IF_NULL(node_prim);
return node_prim->name();
}
// Assign the value of the function argument 'fn' to the variable 'node_prim' using the 'GetValueNode' template function,
// which returns a pointer to a 'PrimitivePtr' object
auto node_prim = GetValueNode<PrimitivePtr>(fn);
// Check if 'node_prim' is a null pointer, and if so, throw an exception
MS_EXCEPTION_IF_NULL(node_prim);
// Return the name of the 'PrimitivePtr' object pointed to by 'node_prim'
return node_prim->name();
// Define the function `DoFusion` in the `Util` namespace, which takes in a `FuncGraphPtr` named `func_graph`, a `std::string` named `cnode_name`, and a `std::string` named `fused_cnode_name`
void Util::DoFusion(const FuncGraphPtr &func_graph, const std::string &cnode_name,
const std::string &fused_cnode_name) {
// Check if `func_graph` is null, and throw an exception if it is
MS_EXCEPTION_IF_NULL(func_graph);
// Create a vector of `AnfNodePtr` named `node_list` and initialize it with the result of calling the `TopoSort` function on the `return` node of `func_graph`
std::vector<AnfNodePtr> node_list = TopoSort(func_graph->get_return());
// ...
}
// Declare a vector to store pointers to AnfNode objects
std::vector<AnfNodePtr> single_nodes;
// Declare a vector to store strings representing weight names
std::vector<std::string> weight_names;
// Declare a vector to store integers representing indices
std::vector<int64_t> indices;
// Iterate over each AnfNodePtr object in the node_list
for (const AnfNodePtr &node : node_list) {
// Check if the current node is not null and is of type CNode
if (node != nullptr && node->isa<CNode>()) {
// Check if the primitive name of the current CNode matches the specified cnode_name
if (GetPrimitiveName(node->cast<CNodePtr>()) == cnode_name) {
// If the conditions are met, add the current node to the single_nodes vector
single_nodes.push_back(node);
auto weight_name_value_node =
common::AnfAlgo::GetInputNode(node->cast<CNodePtr>(), kNodeInputWeightNameOffset)->cast<ValueNodePtr>();
// Get the input node of the current node at the specified offset using AnfAlgo::GetInputNode() function
auto weight_name_value_node = common::AnfAlgo::GetInputNode(node->cast<CNodePtr>(), kNodeInputWeightNameOffset)->cast<ValueNodePtr>();
// Get the value stored in the ValueNode as a string using GetValue<std::string>() function
const std::string &weight_name = GetValue<std::string>(weight_name_value_node->value());
// Add the weight name to the weight_names vector
weight_names.push_back(weight_name);
auto weight_index_value_node =
common::AnfAlgo::GetInputNode(node->cast<CNodePtr>(), kNodeInputWeightIndexOffset)->cast<ValueNodePtr>();
// Get the input node of the current CNode using the AnfAlgo::GetInputNode function
auto weight_index_value_node = common::AnfAlgo::GetInputNode(node->cast<CNodePtr>(), kNodeInputWeightIndexOffset)->cast<ValueNodePtr>();
// Extract the value of the weight index from the value node
int64_t weight_index = GetValue<int64_t>(weight_index_value_node->value());
// Add the weight index to the indices vector
indices.push_back(weight_index);
}
}
}
// Create a shared pointer to a Primitive object using the provided fused_cnode_name
auto prim = std::make_shared<Primitive>(fused_cnode_name);
// Check if the prim pointer is null, and throw an exception if it is
MS_EXCEPTION_IF_NULL(prim);
// Create an empty vector to store the inputs for the fused node
std::vector<AnfNodePtr> fused_node_inputs = {};
// Add the prim object as a NewValueNode to the fused_node_inputs vector
fused_node_inputs.push_back(NewValueNode(prim));
// Iterate over the single_nodes vector using a lambda function
(void)std::for_each(single_nodes.begin(), single_nodes.end(), [&](const AnfNodePtr &node) {
// Get the input node of the current node and add it to the fused_node_inputs vector
fused_node_inputs.push_back(common::AnfAlgo::GetInputNode(node->cast<CNodePtr>(), 0));
});
auto fused_cnode = func_graph->NewCNode(fused_node_inputs);
MS_EXCEPTION_IF_NULL(fused_cnode);
common::AnfAlgo::SetNodeAttr(kAttrPsKey, MakeValue(weight_names), fused_cnode);
common::AnfAlgo::SetNodeAttr(kAttrIndex, MakeValue(indices), fused_cnode);
common::AnfAlgo::SetNodeAttr(kAttrPrimitiveTarget, MakeValue(kCPUDevice), fused_cnode);
// Create a new CNode in the given function graph, using the provided fused_node_inputs as inputs
auto fused_cnode = func_graph->NewCNode(fused_node_inputs);
auto kernel_info = std::make_shared<device::KernelInfo>();
MS_EXCEPTION_IF_NULL(kernel_info);
fused_cnode->set_kernel_info(kernel_info);
auto kernel_build_info = GenerateKernelBuildInfo(single_nodes);
AnfAlgo::SetSelectKernelBuildInfo(kernel_build_info, fused_cnode.get());
// Check if the fused_cnode is null, and throw an exception if it is
MS_EXCEPTION_IF_NULL(fused_cnode);
AbstractBasePtrList abstract_list;
for (const auto &node : single_nodes) {
// Set the attribute with key kAttrPsKey in the fused_cnode to the value of weight_names
common::AnfAlgo::SetNodeAttr(kAttrPsKey, MakeValue(weight_names), fused_cnode);
// Set the attribute with key kAttrIndex in the fused_cnode to the value of indices
common::AnfAlgo::SetNodeAttr(kAttrIndex, MakeValue(indices), fused_cnode);
// Set the attribute with key kAttrPrimitiveTarget in the fused_cnode to the value of kCPUDevice
common::AnfAlgo::SetNodeAttr(kAttrPrimitiveTarget, MakeValue(kCPUDevice), fused_cnode);
// Create a shared pointer to a new instance of the KernelInfo class and assign it to the variable "kernel_info"
auto kernel_info = std::make_shared<device::KernelInfo>();
// Check if the kernel_info pointer is null, and throw an exception if it is
MS_EXCEPTION_IF_NULL(kernel_info);
// Set the kernel_info of the fused_cnode to the newly created kernel_info
fused_cnode->set_kernel_info(kernel_info);
// Generate the kernel build information using the single_nodes
auto kernel_build_info = GenerateKernelBuildInfo(single_nodes);
// Set the kernel build information for the fused_cnode using the AnfAlgo::SetSelectKernelBuildInfo function
AnfAlgo::SetSelectKernelBuildInfo(kernel_build_info, fused_cnode.get());
// Create an empty list of AbstractBasePtr objects called abstract_list
AbstractBasePtrList abstract_list;
// Iterate over each element in the single_nodes container using a range-based for loop
for (const auto &node : single_nodes) {
// Cast the current node to a CNodePtr object and assign it to the variable cnode
auto cnode = node->cast<CNodePtr>();
MS_EXCEPTION_IF_NULL(cnode);
abstract_list.push_back(cnode->abstract());
}
auto abstract_tuple = std::make_shared<abstract::AbstractTuple>(abstract_list);
MS_EXCEPTION_IF_NULL(abstract_tuple);
fused_cnode->set_abstract(abstract_tuple);
// Throw an exception if cnode is a null pointer
MS_EXCEPTION_IF_NULL(cnode);
// Add the abstract value of cnode to the abstract_list
abstract_list.push_back(cnode->abstract());
}
// Create a shared pointer to an AbstractTuple object called abstract_tuple, passing in the abstract_list as an argument
auto abstract_tuple = std::make_shared<abstract::AbstractTuple>(abstract_list);
// Throw an exception if abstract_tuple is a null pointer
MS_EXCEPTION_IF_NULL(abstract_tuple);
// Set the abstract value of fused_cnode to the abstract_tuple
fused_cnode->set_abstract(abstract_tuple);
// Get the manager of the given func_graph
auto manager = func_graph->manager();
// Check if the manager is null, throw an exception if it is
MS_EXCEPTION_IF_NULL(manager);
// Iterate over each node in the single_nodes container
for (const auto &node : single_nodes) {
// Replace the current node with the fused_cnode using the manager's Replace function
// If the replacement fails, throw an exception
if (!manager->Replace(node, fused_cnode)) {
MS_LOG(EXCEPTION) << "manager replace node failed";
}
}
return;
}
// Return from the function
return;
// Function to generate kernel build information based on a list of nodes
kernel::KernelBuildInfoPtr Util::GenerateKernelBuildInfo(const std::vector<AnfNodePtr> &node_list) {
// Initialize vectors to store device format, device type, and output shape information
std::vector<std::string> inputs_device_format;
std::vector<std::string> outputs_device_format;
std::vector<TypeId> inputs_device_type;
std::vector<TypeId> outputs_device_type;
std::vector<std::vector<size_t>> outputs_shape;
// Create a builder object to build the kernel build information
kernel::KernelBuildInfo::KernelBuildInfoBuilder builder;
// Iterate over the node list
for (size_t idx = 0; idx < node_list.size(); ++idx) {
auto cnode = utils::cast<CNodePtr>(node_list[idx]);
MS_EXCEPTION_IF_NULL(cnode);
// Get the number of input tensors for the current node
size_t input_num = common::AnfAlgo::GetInputTensorNum(cnode);
// Iterate over the input tensors
for (size_t input_index = 0; input_index < input_num; ++input_index) {
// Add the default device format for the input tensor
(void)inputs_device_format.emplace_back(kOpFormat_DEFAULT);
// Get the device type for the input tensor and add it to the vector
inputs_device_type.push_back(common::AnfAlgo::GetPrevNodeOutputInferDataType(cnode, input_index));
}
// Get the number of output tensors for the current node
size_t output_num = common::AnfAlgo::GetOutputTensorNum(cnode);
// Iterate over the output tensors
for (size_t output_index = 0; output_index < output_num; ++output_index) {
// Add the default device format for the output tensor
(void)outputs_device_format.emplace_back(kOpFormat_DEFAULT);
// Get the device type for the output tensor and add it to the vector
outputs_device_type.push_back(common::AnfAlgo::GetOutputInferDataType(cnode, output_index));
// Get the output shape for the output tensor and add it to the vector
outputs_shape.push_back(common::AnfAlgo::GetOutputInferShape(cnode, output_index));
}
}
// Set the inputs format, outputs format, inputs device type, and outputs device type using the builder
builder.SetInputsFormat(inputs_device_format);
builder.SetOutputsFormat(outputs_device_format);
builder.SetInputsDeviceType(inputs_device_type);
builder.SetOutputsDeviceType(outputs_device_type);
// Build and return the kernel build information
return builder.Build();
}
} // namespace ps
} // namespace mindspore
// End of namespace ps
} // namespace mindspore