/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 "mxnet/c_api.h" // MXGetGPUCount() #include "mxnet-cpp/MxNetCpp.h" using namespace mxnet::cpp; static bool test_single_key(const Context &context, const std::string &context_str) { std::string key = "singlekeytest-" + context_str; NDArray result(Shape(4), context); NDArray result_cpu; // initialize data NDArray data_cpu({0.f, 233.f, -0.12f, 9.f}, Shape(4), Context::cpu()); NDArray data = data_cpu.Copy(context); NDArray::WaitAll(); KVStore::Init(key, data); NDArray::WaitAll(); // retrieve result KVStore::Pull(key, &result); NDArray::WaitAll(); result_cpu = result.Copy(Context::cpu()); NDArray::WaitAll(); // compare for (size_t j=0; j < result_cpu.Size(); j++) { if (result_cpu.GetData()[j] != data_cpu.GetData()[j]) { LG << "Error: wrong initialized data in singlekeytest-" << context_str << ", expect " << data_cpu.GetData()[j] << " got " << result_cpu.GetData()[j]; return false; } } // push gradient NDArray grad_cpu({0.1f, -2.f, -4.4f, 0.f}, Shape(4), Context::cpu()); NDArray grad = grad_cpu.Copy(context); NDArray::WaitAll(); KVStore::Push(key, grad); NDArray::WaitAll(); // retrieve result KVStore::Pull(key, &result); NDArray::WaitAll(); result_cpu = result.Copy(Context::cpu()); NDArray::WaitAll(); // compare for (size_t j=0; j < result_cpu.Size(); j++) { if (result_cpu.GetData()[j] != grad_cpu.GetData()[j]) { LG << "Error: wrong gradient data in singlekeytest-" << context_str << ", expect " << grad_cpu.GetData()[j] << " got " << result_cpu.GetData()[j]; return false; } } return true; } static bool test_multiple_key(const Context &context, const std::string &context_str) { std::vector keys(2); keys[0] = "multikeytest-0-" + context_str; keys[1] = "multikeytest-1-" + context_str; std::vector results(2); results[0] = NDArray(Shape(4), context); results[1] = NDArray(Shape(4), context); std::vector results_cpu(2); // initialize data std::vector data_cpu(2); data_cpu[0] = NDArray({0.f, 2.f, -3.12f, 4.f}, Shape(4), Context::cpu()); data_cpu[1] = NDArray({0.8f, -2.f, 6.6f, 77.f}, Shape(4), Context::cpu()); std::vector data(2); data[0] = data_cpu[0].Copy(context); data[1] = data_cpu[1].Copy(context); NDArray::WaitAll(); KVStore::Init(keys, data); NDArray::WaitAll(); // retrieve result KVStore::Pull(keys, &results); NDArray::WaitAll(); results_cpu[0] = results[0].Copy(Context::cpu()); results_cpu[1] = results[1].Copy(Context::cpu()); NDArray::WaitAll(); // compare for (size_t i=0; i < results_cpu.size(); i++) { for (size_t j=0; j < results_cpu[i].Size(); j++) { if (results_cpu[i].GetData()[j] != data_cpu[i].GetData()[j]) { LG << "Error: wrong initialized data in multikeytest-" << context_str << ", expect " << data_cpu[i].GetData()[j] << " got " << results_cpu[i].GetData()[j]; return false; } } } // push gradient, reduce for the second std::vector push_keys(3); push_keys[0] = "multikeytest-0-" + context_str; push_keys[1] = "multikeytest-1-" + context_str; push_keys[2] = "multikeytest-1-" + context_str; std::vector grads_cpu(3); grads_cpu[0] = NDArray({0.2f, -0.3f, -1.1f, 0.0f}, Shape(4), Context::cpu()); grads_cpu[1] = NDArray({2.f, 4.f, -4.f, -5.f}, Shape(4), Context::cpu()); grads_cpu[2] = NDArray({-3.f, -0.2f, 12.f, -9.f}, Shape(4), Context::cpu()); std::vector grads(3); grads[0] = grads_cpu[0].Copy(context); grads[1] = grads_cpu[1].Copy(context); grads[2] = grads_cpu[2].Copy(context); NDArray::WaitAll(); KVStore::Push(push_keys, grads); NDArray::WaitAll(); // retrieve result KVStore::Pull(keys, &results); NDArray::WaitAll(); results_cpu[0] = results[0].Copy(Context::cpu()); results_cpu[1] = results[1].Copy(Context::cpu()); NDArray::WaitAll(); // compare the first for (size_t j=0; j < results_cpu[0].Size(); j++) { if (results_cpu[0].GetData()[j] != grads_cpu[0].GetData()[j]) { LG << "Error: wrong gradient data in multikeytest-" << context_str << ", expect " << grads_cpu[0].GetData()[j] << " got " << results_cpu[0].GetData()[j]; return false; } } // compare the second for (size_t j=0; j < results_cpu[1].Size(); j++) { if (results_cpu[1].GetData()[j] != (grads_cpu[1].GetData()[j] + grads_cpu[2].GetData()[j])) { LG << "Error: wrong reduced gradient data in multikeytest-" << context_str << ", expect " << (grads_cpu[1].GetData()[j] + grads_cpu[2].GetData()[j]) << " got " << results_cpu[1].GetData()[j]; return false; } } return true; } int main(int argc, char** argv) { KVStore::SetType("local"); bool success1 = test_single_key(Context::cpu(), "cpu"); bool success2 = test_multiple_key(Context::cpu(), "cpu"); bool success3 = true; bool success4 = true; int gpu_count = 0; if (MXGetGPUCount(&gpu_count) != 0) { LG << "Error: MXGetGPUCount"; MXNotifyShutdown(); return 1; } if (gpu_count > 0) { success3 = test_single_key(Context::gpu(), "gpu"); success4 = test_multiple_key(Context::gpu(), "gpu"); } int ret = (success1 && success2 && success3 && success4) ? 0 : 1; MXNotifyShutdown(); return ret; }