// cudamatrix/cu-array-test.cc // Copyright 2013 Johns Hopkins University (author: Daniel Povey) // See ../../COPYING for clarification regarding multiple authors // // 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 // // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, // MERCHANTABLITY OR NON-INFRINGEMENT. // See the Apache 2 License for the specific language governing permissions and // limitations under the License. #include #include #include #include "base/kaldi-common.h" #include "util/common-utils.h" #include "cudamatrix/cu-array.h" using namespace kaldi; namespace kaldi { template void AssertEqual(const std::vector &vec1, const std::vector &vec2) { // use this instead of "vec1 == vec2" because // for doubles and floats, this can fail if we // have NaNs, even if identical. KALDI_ASSERT(vec1.size() == vec2.size()); if (vec1.size() > 0) { const char *p1 = reinterpret_cast(&(vec1[0])); const char *p2 = reinterpret_cast(&(vec2[0])); size_t size = sizeof(T) * vec1.size(); for (size_t i = 0; i < size; i++) KALDI_ASSERT(p1[i] == p2[i]); } } template static void UnitTestCuArray() { for (int32 i = 0; i < 30; i++) { int32 size = Rand() % 5; size = size * size * size; // Have a good distribution of sizes, including >256. int32 size2 = Rand() % 4; std::vector vec(size); std::vector garbage_vec(size2); // We just use garbage_vec to make sure // we sometimes resize from empty, // sometimes not. int32 byte_size = size * sizeof(T); std::vector rand_c(byte_size); for (size_t i = 0; i < byte_size; i++) rand_c[i] = Rand() % 256; if (!vec.empty()) { std::memcpy((void*)&(vec[0]), (void*)&(rand_c[0]), byte_size); } { // test constructor from vector and CopyToVec. CuArray cu_vec(vec); std::vector vec2; cu_vec.CopyToVec(&vec2); T *vec22 = new T[vec.size()]; cu_vec.CopyToHost(vec22); delete[] vec22; } { // test assignment operator from CuArray. CuArray cu_vec(vec); CuArray cu_vec2(garbage_vec); cu_vec2 = cu_vec; std::vector vec2; cu_vec2.CopyToVec(&vec2); AssertEqual(vec, vec2); KALDI_ASSERT(cu_vec2.Dim() == int32(vec2.size())); // test Dim() } { // test resize with resize_type = kSetZero. CuArray cu_vec(vec); cu_vec.Resize(size, kSetZero); std::vector vec2(vec); if (!vec2.empty()) std::memset(&(vec2[0]), 0, vec2.size() * sizeof(T)); std::vector vec3; cu_vec.CopyToVec(&vec3); AssertEqual(vec2, vec3); // testing equality of zero arrays. } if (sizeof(T) == sizeof(int32) && size > 0) { // test Set for type int32, or same size. CuArray cu_vec(vec); cu_vec.Set(vec[0]); for (size_t i = 1; i < vec.size(); i++) vec[i] = vec[0]; std::vector vec2; cu_vec.CopyToVec(&vec2); AssertEqual(vec, vec2); } } } } // namespace kaldi int main() { SetVerboseLevel(1); int32 loop = 0; #if HAVE_CUDA == 1 for (; loop < 2; loop++) { CuDevice::Instantiate().SetDebugStrideMode(true); if (loop == 0) CuDevice::Instantiate().SelectGpuId("no"); else CuDevice::Instantiate().SelectGpuId("yes"); #endif //kaldi::UnitTestCuArray(); kaldi::UnitTestCuArray(); kaldi::UnitTestCuArray(); kaldi::UnitTestCuArray >(); if (loop == 0) KALDI_LOG << "Tests without GPU use succeeded."; else KALDI_LOG << "Tests with GPU use (if available) succeeded."; #if HAVE_CUDA == 1 } CuDevice::Instantiate().PrintProfile(); #endif return 0; }