|
|
|
@ -305,6 +305,9 @@ Status BatchOp::MapColumns(std::pair<std::unique_ptr<TensorQTable>, CBatchInfo>
|
|
|
|
|
for (size_t i = 0; i < out_cols.size(); i++) {
|
|
|
|
|
size_t col_id = column_name_id_map_[out_col_names_[i]];
|
|
|
|
|
size_t row_id = 0;
|
|
|
|
|
CHECK_FAIL_RETURN_UNEXPECTED(num_rows == out_cols[i].size(),
|
|
|
|
|
"column: " + out_col_names_[i] + " expects: " + std::to_string(num_rows) +
|
|
|
|
|
" rows returned from per_batch_map, gets: " + std::to_string(out_cols[i].size()));
|
|
|
|
|
for (auto &t_row : *out_q_table) {
|
|
|
|
|
t_row[col_id] = out_cols[i][row_id++];
|
|
|
|
|
}
|
|
|
|
@ -334,7 +337,7 @@ Status BatchOp::InvokeBatchSizeFunc(int32_t *batch_size, CBatchInfo info) {
|
|
|
|
|
// Acquire Python GIL
|
|
|
|
|
py::gil_scoped_acquire gil_acquire;
|
|
|
|
|
if (Py_IsInitialized() == 0) {
|
|
|
|
|
return Status(StatusCode::kPythonInterpreterFailure, "Python Interpreter is finalized");
|
|
|
|
|
return Status(StatusCode::kPythonInterpreterFailure, "Python Interpreter is finalized.");
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
py::object size = batch_size_func_(info);
|
|
|
|
@ -350,7 +353,7 @@ Status BatchOp::InvokeBatchSizeFunc(int32_t *batch_size, CBatchInfo info) {
|
|
|
|
|
"Invalid parameter, batch size function should return an integer greater than 0.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Status(StatusCode::kOK, "Batch size func call succeed");
|
|
|
|
|
return Status(StatusCode::kOK, "Batch size func call succeed.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Status BatchOp::InvokeBatchMapFunc(TensorTable *input, TensorTable *output, CBatchInfo info) {
|
|
|
|
@ -358,7 +361,7 @@ Status BatchOp::InvokeBatchMapFunc(TensorTable *input, TensorTable *output, CBat
|
|
|
|
|
// Acquire Python GIL
|
|
|
|
|
py::gil_scoped_acquire gil_acquire;
|
|
|
|
|
if (Py_IsInitialized() == 0) {
|
|
|
|
|
return Status(StatusCode::kPythonInterpreterFailure, "Python Interpreter is finalized");
|
|
|
|
|
return Status(StatusCode::kPythonInterpreterFailure, "Python Interpreter is finalized.");
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
// Prepare batch map call back parameters
|
|
|
|
@ -377,11 +380,24 @@ Status BatchOp::InvokeBatchMapFunc(TensorTable *input, TensorTable *output, CBat
|
|
|
|
|
py::object ret_py_obj = batch_map_func_(*input_args);
|
|
|
|
|
// Parse batch map return value
|
|
|
|
|
py::tuple ret_tuple = py::cast<py::tuple>(ret_py_obj);
|
|
|
|
|
CHECK_FAIL_RETURN_UNEXPECTED(py::isinstance<py::tuple>(ret_tuple), "Batch map function should return a tuple");
|
|
|
|
|
CHECK_FAIL_RETURN_UNEXPECTED(ret_tuple.size() == out_col_names_.size(), "Incorrect number of columns returned.");
|
|
|
|
|
CHECK_FAIL_RETURN_UNEXPECTED(py::isinstance<py::tuple>(ret_tuple), "Batch map function should return a tuple.");
|
|
|
|
|
CHECK_FAIL_RETURN_UNEXPECTED(
|
|
|
|
|
ret_tuple.size() == out_col_names_.size(),
|
|
|
|
|
"Incorrect number of columns returned. expects: " + std::to_string(out_col_names_.size()) +
|
|
|
|
|
" gets: " + std::to_string(ret_tuple.size()));
|
|
|
|
|
for (size_t i = 0; i < ret_tuple.size(); i++) {
|
|
|
|
|
TensorRow output_batch;
|
|
|
|
|
// If user returns a type that is neither a list nor an array, issue a error msg.
|
|
|
|
|
if (py::isinstance<py::array>(ret_tuple[i])) {
|
|
|
|
|
MS_LOG(WARNING) << "column: " << out_col_names_[i]
|
|
|
|
|
<< " returned by per_batch_map is a np.array. Please use list instead.";
|
|
|
|
|
} else if (!py::isinstance<py::list>(ret_tuple[i])) {
|
|
|
|
|
MS_LOG(ERROR) << "column: " << out_col_names_[i]
|
|
|
|
|
<< " returned by per_batch_map is not a list, this could lead to conversion failure.";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
py::list output_list = py::cast<py::list>(ret_tuple[i]);
|
|
|
|
|
|
|
|
|
|
for (size_t j = 0; j < output_list.size(); j++) {
|
|
|
|
|
std::shared_ptr<Tensor> out;
|
|
|
|
|
RETURN_IF_NOT_OK(Tensor::CreateFromNpArray(py::cast<py::array>(output_list[j]), &out));
|
|
|
|
|