Repository: incubator-singa Updated Branches: refs/heads/master 61ec2ec74 -> 1996e8a95
http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/595302a3/test/singa/test_opencl.cc ---------------------------------------------------------------------- diff --git a/test/singa/test_opencl.cc b/test/singa/test_opencl.cc index 3ce1889..d464bc9 100644 --- a/test/singa/test_opencl.cc +++ b/test/singa/test_opencl.cc @@ -23,419 +23,286 @@ #include "singa/core/device.h" #include "singa/core/tensor.h" #include "singa/proto/core.pb.h" + using singa::CppCPU; using singa::Block; using singa::Shape; using singa::Tensor; #ifdef USE_OPENCL + using singa::OpenclDevice; + class OpenCL_TensorMath : public ::testing::Test { protected: OpenCL_TensorMath() { - for (int i = 0; i < 4; i++) { - float4[i] = (float)i; - float4zero[i] = 0.0f; - } - - for (int i = 0; i < 16; i++) { - float16[i] = (float)i; - float16zero[i] = 0.0f; - } - auto ocl_dev = std::make_shared<OpenclDevice>(); - - tf4in = Tensor(Shape{1, 4}, ocl_dev); - tf4in.CopyDataFromHostPtr(float4, 4); - - tf4zin = Tensor(Shape{1, 4}, ocl_dev); - tf4zin.CopyDataFromHostPtr(float4zero, 4); - - tf16in = Tensor(Shape{4, 4}, ocl_dev); - tf16in.CopyDataFromHostPtr(float16, 16); - - tf16zin = Tensor(Shape{4, 4}, ocl_dev); - tf16zin.CopyDataFromHostPtr(float16zero, 16); - - float empty[10000] = {}; + + a = Tensor(Shape{6}, ocl_dev); + b = Tensor(Shape{6}, ocl_dev); + c = Tensor(Shape{6, 1}, ocl_dev); + d = Tensor(Shape{3, 2}, ocl_dev); + e = Tensor(Shape{3, 2}, ocl_dev); empty10k = Tensor(Shape{10000}, ocl_dev); - empty10k.CopyDataFromHostPtr(empty, 10000); + + a.CopyDataFromHostPtr<float>(dat1, 6); + b.CopyDataFromHostPtr<float>(dat2, 6); + e.CopyDataFromHostPtr<float>(dat1, 6); } - - float float4[4]; - float float4zero[4]; - float float16[16]; - float float16zero[16]; - - Tensor tf4in, tf16in; - Tensor tf4zin, tf16zin; + + Tensor a, b, c, d, e; Tensor empty10k; + const float dat1[6] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; + const float dat2[6] = {1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f}; }; -// Makes a float array and fills it with increasing values from 0. -float* MakeMatrix(const int size) { - float* mat = new float[size]; - for (int i = 0; i < size; i++) - mat[i] = i; - return mat; -} - - -TEST(OpenclDevice, Constructor) { - OpenclDevice dev; - EXPECT_EQ(0, dev.id()); -} - - -TEST(OpenclDevice, MemoryAllocFree) { - OpenclDevice dev; - Block* b = dev.NewBlock(4); - EXPECT_NE(nullptr, b); - EXPECT_EQ(4u, b->size()); - dev.FreeBlock(b); -} - -// Tests for integrity of one round of data transfer to an OpenCL device and back. -TEST(OpenclDevice, CopyDataToFrom) { - OpenclDevice dev; - CppCPU host; - - Block* a = host.NewBlock(4); - Block* b = dev.NewBlock(4); - Block* c = host.NewBlock(4); - - // Allocate the Block object on the host. - char s[] = {'a', 'b', 'c', 'x'}; - host.CopyDataFromHostPtr(a, s, 4); - - // Copy back and forth. - dev.CopyDataToFrom(b, a, 4, singa::kHostToDevice); - dev.CopyDataToFrom(c, b, 4, singa::kDeviceToHost); - - const char* astr = static_cast<const char*>(c->data()); - EXPECT_EQ('a', astr[0]); - EXPECT_EQ('b', astr[1]); - EXPECT_EQ('x', astr[3]); -} - - -TEST(OpenclDevice, DuplicateDataOnDevice) { - OpenclDevice dev; - CppCPU host; - - Block* a = host.NewBlock(4); - Block* b = dev.NewBlock(4); - Block* c = dev.NewBlock(4); - Block* d = host.NewBlock(4); - - // Allocate the Block object on the host. - char s[] = {'a', 'b', 'c', 'x'}; - host.CopyDataFromHostPtr(a, s, 4); - - // Copy to device and duplicate. - dev.CopyDataToFrom(b, a, 4, singa::kHostToDevice); - dev.CopyDataToFrom(c, b, 4, singa::kDeviceToDevice); - dev.CopyDataToFrom(d, c, 4, singa::kDeviceToHost); - - const char* astr = static_cast<const char*>(d->data()); - EXPECT_EQ('a', astr[0]); - EXPECT_EQ('b', astr[1]); - EXPECT_EQ('x', astr[3]); -} - -// Tensor tests, uses OpenCL_TensorMath class defined above. - -TEST_F(OpenCL_TensorMath, CopyDataToDevice) { - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_EQ(1.0f, out[1]); - EXPECT_EQ(3.0f, out[3]); -} - - TEST_F(OpenCL_TensorMath, MemberAbs) { - tf4in = Abs(tf4in); - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_EQ(0.0f, out[0]); - EXPECT_EQ(1.0f, out[1]); - EXPECT_EQ(2.0f, out[2]); - EXPECT_EQ(3.0f, out[3]); + Tensor aa = a.Clone(); + Tensor bb = b.Clone(); + Tensor cc = aa - bb; + + cc.ToHost(); + const float *dptr = cc.data<float>(); + EXPECT_NEAR(-0.1, dptr[0], 1e-5); + EXPECT_NEAR(-0.1, dptr[1], 1e-5); + EXPECT_NEAR(-0.1, dptr[2], 1e-5); + + Tensor p = Abs(cc); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(0.1, dptr1[0], 1e-5); + EXPECT_NEAR(0.1, dptr1[1], 1e-5); + EXPECT_NEAR(0.1, dptr1[2], 1e-5); } -TEST_F(OpenCL_TensorMath, MemberExp) { - tf4in = Exp(tf4in); +//TEST_F(OpenCL_TensorMath, MemberClamp) { } - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - EXPECT_NEAR(exp(0.0f), out[0], 1e-5); - EXPECT_NEAR(exp(1.0f), out[1], 1e-5); - EXPECT_NEAR(exp(2.0f), out[2], 1e-5); - EXPECT_NEAR(exp(3.0f), out[3], 1e-5); +TEST_F(OpenCL_TensorMath, MemberExp) { + Tensor p = Exp(a); + + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(exp(1.0f), dptr1[0], 1e-5); + EXPECT_NEAR(exp(2.0f), dptr1[1], 1e-5); + EXPECT_NEAR(exp(3.0f), dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberLog) { - tf4in = Log(tf4in); - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - -// EXPECT_NEAR(log(0.0f), out[0], 1e-5); // Evaluates to neg infinity. - EXPECT_NEAR(log(1.0f), out[1], 1e-5); - EXPECT_NEAR(log(2.0f), out[2], 1e-5); - EXPECT_NEAR(log(3.0f), out[3], 1e-5); + Tensor p = Log(a); + + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(log(1.0f), dptr1[0], 1e-5); + EXPECT_NEAR(log(2.0f), dptr1[1], 1e-5); + EXPECT_NEAR(log(3.0f), dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberReLU) { - tf4in -= 2.0f; - Tensor result = ReLU(tf4in); - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_NEAR(0.0f, out[0], 1e-5); - EXPECT_NEAR(0.0f, out[1], 1e-5); - EXPECT_NEAR(0.0f, out[2], 1e-5); - EXPECT_NEAR(1.0f, out[3], 1e-5); + Tensor aa = a.Clone(); + Tensor cc = aa - 2.0f; + + cc.ToHost(); + const float *dptr = cc.data<float>(); + EXPECT_NEAR(-1.0f, dptr[0], 1e-5); + EXPECT_NEAR(0.0f, dptr[1], 1e-5); + EXPECT_NEAR(1.0f, dptr[2], 1e-5); + + Tensor p = ReLU(cc); + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(0.0f, dptr1[0], 1e-5); + EXPECT_NEAR(0.0f, dptr1[1], 1e-5); + EXPECT_NEAR(1.0f, dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberSigmoid) { - tf4in = Sigmoid(tf4in); - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_NEAR(1.0f / (1.0f + exp(-0.0f)), out[0], 1e-5); - EXPECT_NEAR(1.0f / (1.0f + exp(-1.0f)), out[1], 1e-5); - EXPECT_NEAR(1.0f / (1.0f + exp(-2.0f)), out[2], 1e-5); + Tensor p = Sigmoid(a); + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(1.0f / (1.0f + exp(-1.0f)), dptr1[0], 1e-5); + EXPECT_NEAR(1.0f / (1.0f + exp(-2.0f)), dptr1[1], 1e-5); + EXPECT_NEAR(1.0f / (1.0f + exp(-3.0f)), dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberSign) { - tf4in -= 1.0f; - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_NEAR(-1.0f, out[0], 1e-5); - EXPECT_NEAR(0.0f, out[1], 1e-5); - EXPECT_NEAR(1.0f, out[2], 1e-5); - EXPECT_NEAR(2.0f, out[3], 1e-5); + Tensor aa = a.Clone(); + Tensor cc = aa - 2.0f; + cc.ToHost(); + const float *dptr = cc.data<float>(); + EXPECT_NEAR(-1.0f, dptr[0], 1e-5); + EXPECT_NEAR(0.0f, dptr[1], 1e-5); + EXPECT_NEAR(1.0f, dptr[2], 1e-5); + + Tensor p = Sign(cc); + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_EQ(0.0f, dptr1[0]); + EXPECT_EQ(0.0f, dptr1[1]); + EXPECT_EQ(1.0f, dptr1[2]); } TEST_F(OpenCL_TensorMath, MemberSqrt) { - tf4in = Sqrt(tf4in); - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_NEAR(0.0f, out[0], 1e-5); - EXPECT_NEAR(1.0f, out[1], 1e-5); - EXPECT_NEAR(sqrt(2.0f), out[2], 1e-5); - EXPECT_NEAR(sqrt(3.0f), out[3], 1e-5); + Tensor p = Sqrt(a); + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(sqrt(1.0), dptr1[0], 1e-5); + EXPECT_NEAR(sqrt(2.0), dptr1[1], 1e-5); + EXPECT_NEAR(sqrt(3.0), dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberSquare) { - tf4in = Square(tf4in); - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_NEAR(0.0f, out[0], 1e-5); - EXPECT_NEAR(1.0f, out[1], 1e-5); - EXPECT_NEAR(4.0f, out[2], 1e-5); - EXPECT_NEAR(9.0f, out[3], 1e-5); + Tensor p = Square(a); + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(1.0, dptr1[0], 1e-5); + EXPECT_NEAR(4.0, dptr1[1], 1e-5); + EXPECT_NEAR(9.0, dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberTanh) { - tf4in = Tanh(tf4in); - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_NEAR(0.0f, out[0], 1e-5); - EXPECT_NEAR(tanh(1.0f), out[1], 1e-5); - EXPECT_NEAR(tanh(2.0f), out[2], 1e-5); - EXPECT_NEAR(tanh(3.0f), out[3], 1e-5); + Tensor p = Tanh(a); + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_NEAR(tanh(1.0), dptr1[0], 1e-5); + EXPECT_NEAR(tanh(2.0), dptr1[1], 1e-5); + EXPECT_NEAR(tanh(3.0), dptr1[2], 1e-5); } - TEST_F(OpenCL_TensorMath, Sum) { - Tensor result = Sum(tf4in, 0); - - result.ToHost(); - const float* out = result.data<float>(); + float result = Sum(a); + EXPECT_EQ(21.0f, result); +} - EXPECT_NEAR(0.0f, out[0], 1e-5); - EXPECT_NEAR(1.0f, out[1], 1e-5); - EXPECT_NEAR(2.0f, out[2], 1e-5); - EXPECT_NEAR(3.0f, out[3], 1e-5); +/* +TEST_F(OpenCL_TensorMath, SoftMax) { + Tensor p1 = SoftMax(Reshape(e, Shape{1, 6})); + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + float sum = 0; + for (int i = 0; i < 6; i++) sum += exp(i + 1); + EXPECT_NEAR(exp(1) / sum, dptr1[0], 1e-5); + EXPECT_NEAR(exp(3) / sum, dptr1[2], 1e-5); + EXPECT_NEAR(exp(5) / sum, dptr1[4], 1e-5); + EXPECT_NEAR(exp(2) / sum, dptr1[1], 1e-5); + EXPECT_NEAR(exp(4) / sum, dptr1[3], 1e-5); + EXPECT_NEAR(exp(6) / sum, dptr1[5], 1e-5); + + Tensor p2 = SoftMax(e); + p2.ToHost(); + const float *dptr2 = p2.data<float>(); + EXPECT_NEAR(exp(1) / (exp(1) + exp(2)), dptr2[0], 1e-5); + EXPECT_NEAR(exp(2) / (exp(1) + exp(2)), dptr2[1], 1e-5); } +*/ TEST_F(OpenCL_TensorMath, MemberLT) { - Tensor result = tf4in < 2.0f; - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_FLOAT_EQ(1.0f, out[0]); - EXPECT_FLOAT_EQ(1.0f, out[1]); - EXPECT_FLOAT_EQ(0.0f, out[2]); - EXPECT_FLOAT_EQ(0.0f, out[3]); + Tensor p1 = a < 2.0f; + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_FLOAT_EQ(1.0f, dptr1[0]); + EXPECT_FLOAT_EQ(0.0f, dptr1[1]); + EXPECT_FLOAT_EQ(0.0f, dptr1[2]); } TEST_F(OpenCL_TensorMath, MemberLE) { - Tensor result = tf4in <= 2.0f; - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_FLOAT_EQ(1.0f, out[0]); - EXPECT_FLOAT_EQ(1.0f, out[1]); - EXPECT_FLOAT_EQ(1.0f, out[2]); - EXPECT_FLOAT_EQ(0.0f, out[3]); + Tensor p1 = a <= 2.0f; + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_FLOAT_EQ(1.0f, dptr1[0]); + EXPECT_FLOAT_EQ(1.0f, dptr1[1]); + EXPECT_FLOAT_EQ(0.0f, dptr1[2]); } TEST_F(OpenCL_TensorMath, MemberGT) { - Tensor result = tf4in > 2.0f; - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out[0]); - EXPECT_FLOAT_EQ(0.0f, out[1]); - EXPECT_FLOAT_EQ(0.0f, out[2]); - EXPECT_FLOAT_EQ(1.0f, out[3]); + Tensor p1 = a > 2.0f; + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_FLOAT_EQ(0.0f, dptr1[0]); + EXPECT_FLOAT_EQ(0.0f, dptr1[1]); + EXPECT_FLOAT_EQ(1.0f, dptr1[2]); } TEST_F(OpenCL_TensorMath, MemberGE) { - Tensor result = tf4in >= 2.0f; - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out[0]); - EXPECT_FLOAT_EQ(0.0f, out[1]); - EXPECT_FLOAT_EQ(1.0f, out[2]); - EXPECT_FLOAT_EQ(1.0f, out[3]); + Tensor p1 = a >= 2.0f; + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_FLOAT_EQ(0.0f, dptr1[0]); + EXPECT_FLOAT_EQ(1.0f, dptr1[1]); + EXPECT_FLOAT_EQ(1.0f, dptr1[2]); } TEST_F(OpenCL_TensorMath, MemberPow) { - Tensor result = Pow(tf4in, 2.0f); - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out[0]); - EXPECT_FLOAT_EQ(1.0f, out[1]); - EXPECT_FLOAT_EQ(4.0f, out[2]); - EXPECT_FLOAT_EQ(9.0f, out[3]); - - result = Pow(tf4in, tf4in); - - result.ToHost(); - const float* out1 = result.data<float>(); - - EXPECT_FLOAT_EQ(1.0f, out1[0]); // 0 ^ 0 is 1, apparently. - EXPECT_FLOAT_EQ(1.0f, out1[1]); - EXPECT_FLOAT_EQ(4.0f, out1[2]); - EXPECT_FLOAT_EQ(27.0f, out1[3]); + Tensor p1 = Pow(b, 3.0f); + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_FLOAT_EQ(pow(1.1f, 3.0f), dptr1[0]); + EXPECT_FLOAT_EQ(pow(2.1f, 3.0f), dptr1[1]); + EXPECT_FLOAT_EQ(pow(3.1f, 3.0f), dptr1[2]); + + Tensor p2 = Pow(a,b); + p2.ToHost(); + const float *dptr2 = p2.data<float>(); + EXPECT_FLOAT_EQ(pow(1.0f,1.1f), dptr2[0]); + EXPECT_FLOAT_EQ(pow(2.0f,2.1f), dptr2[1]); + EXPECT_FLOAT_EQ(pow(3.0f,3.1f), dptr2[2]); } TEST_F(OpenCL_TensorMath, MemberSub) { - Tensor result = tf4in - tf4zin; - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out[0]); - EXPECT_FLOAT_EQ(1.0f, out[1]); - EXPECT_FLOAT_EQ(2.0f, out[2]); - EXPECT_FLOAT_EQ(3.0f, out[3]); - - result = tf4in - 0.0f; - - result.ToHost(); - const float* out1 = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out1[0]); - EXPECT_FLOAT_EQ(1.0f, out1[1]); - EXPECT_FLOAT_EQ(2.0f, out1[2]); - EXPECT_FLOAT_EQ(3.0f, out1[3]); + Tensor p1 = a - b; + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_NEAR(-0.1, dptr1[0], 1e-5); + EXPECT_NEAR(-0.1, dptr1[1], 1e-5); + EXPECT_NEAR(-0.1, dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberEltwiseMult) { - Tensor result = tf4in * tf4zin; - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out[0]); - EXPECT_FLOAT_EQ(0.0f, out[1]); - EXPECT_FLOAT_EQ(0.0f, out[2]); - EXPECT_FLOAT_EQ(0.0f, out[3]); - - result = tf4in * 10.0f; - - result.ToHost(); - const float* out1 = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out1[0]); - EXPECT_FLOAT_EQ(10.0f, out1[1]); - EXPECT_FLOAT_EQ(20.0f, out1[2]); - EXPECT_FLOAT_EQ(30.0f, out1[3]); + Tensor p1 = a * b; + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_NEAR(1.0 * 1.1, dptr1[0], 1e-5); + EXPECT_NEAR(2.0 * 2.1, dptr1[1], 1e-5); + EXPECT_NEAR(3.0 * 3.1, dptr1[2], 1e-5); } TEST_F(OpenCL_TensorMath, MemberDiv) { - Tensor result = tf4in / tf4in; - - result.ToHost(); - const float* out = result.data<float>(); - -// EXPECT_FLOAT_EQ(0.0f, out[0]); // Divide by zero. - EXPECT_FLOAT_EQ(1.0f, out[1]); - EXPECT_FLOAT_EQ(1.0f, out[2]); - EXPECT_FLOAT_EQ(1.0f, out[3]); - - result = tf4in / 10.0f; - - result.ToHost(); - const float* out1 = result.data<float>(); - - EXPECT_FLOAT_EQ(0.0f, out1[0]); - EXPECT_FLOAT_EQ(0.1f, out1[1]); - EXPECT_FLOAT_EQ(0.2f, out1[2]); - EXPECT_FLOAT_EQ(0.3f, out1[3]); - - result = Div(10.0f, tf4in); - - result.ToHost(); - const float* out2 = result.data<float>(); - -// EXPECT_FLOAT_EQ(0.0f, out[0]); // Divide by 0. - EXPECT_FLOAT_EQ(10.0f, out2[1]); - EXPECT_FLOAT_EQ(5.0f, out2[2]); - EXPECT_NEAR((10.0f / 3.0f), out2[3], 1e-5); + Tensor p1 = a / b; + p1.ToHost(); + const float *dptr1 = p1.data<float>(); + EXPECT_NEAR(1.0 / 1.1, dptr1[0], 1e-5); + EXPECT_NEAR(2.0 / 2.1, dptr1[1], 1e-5); + EXPECT_NEAR(3.0 / 3.1, dptr1[2], 1e-5); + + Tensor p2 = Div(10.0f, b); + p2.ToHost(); + const float *dptr2 = p2.data<float>(); + EXPECT_NEAR(10.0 / 1.1, dptr2[0], 1e-5); + EXPECT_NEAR(10.0 / 2.1, dptr2[1], 1e-5); + EXPECT_NEAR(10.0 / 3.1, dptr2[2], 1e-5); + + Tensor p3 = a / 8.0f; + p3.ToHost(); + const float *dptr3 = p3.data<float>(); + EXPECT_NEAR(1.0 / 8.0, dptr3[0], 1e-5); + EXPECT_NEAR(2.0 / 8.0, dptr3[1], 1e-5); + EXPECT_NEAR(3.0 / 8.0, dptr3[2], 1e-5); } // ************************************** @@ -444,63 +311,49 @@ TEST_F(OpenCL_TensorMath, MemberDiv) { TEST_F(OpenCL_TensorMath, Bernoulli) { const float p = 0.3f; - Bernoulli(p, &empty10k); - empty10k.ToHost(); const float* out = empty10k.data<float>(); - float sum = 0.0f; for (int i = 0; i < 10000; i++) sum += out[i]; - float mean = sum / 10000; - EXPECT_NEAR(mean, p, 1e-2); sum = 0.0f; for (int i = 0; i < 10000; i++) sum += (out[i] - mean) * (out[i] - mean); float variance = sum / 9999; - EXPECT_NEAR(variance, p * (1 - p), 1e-2); } TEST_F(OpenCL_TensorMath, Gaussian) { Gaussian(0.0f, 1.0f, &empty10k); - empty10k.ToHost(); const float* out = empty10k.data<float>(); - float sum = 0.0f; for (int i = 0; i < 10000; i++) sum += out[i]; float mean = sum / 10000; - EXPECT_NEAR(mean, 0.0f, 1e-2); sum = 0.0f; for (int i = 0; i < 10000; i++) sum += (out[i] - mean) * (out[i] - mean); float variance = sum / 9999; - EXPECT_NEAR(variance, 1.0f, 1e-2); } TEST_F(OpenCL_TensorMath, Uniform) { Uniform(0.1f, 0.2f, &empty10k); - empty10k.ToHost(); const float* out = empty10k.data<float>(); - float sum = 0.0f; for (int i = 0; i < 10000; i++) sum += out[i]; float mean = sum / 10000; - EXPECT_NEAR(mean, 0.15f, 1e-2); sum = 0.0f; for (int i = 0; i < 10000; i++) sum += (out[i] - mean) * (out[i] - mean); float variance = sum / 9999; - EXPECT_NEAR(variance, 0.01f, 1e-2); } @@ -509,121 +362,96 @@ TEST_F(OpenCL_TensorMath, Uniform) { // ********************************************************* -TEST_F(OpenCL_TensorMath, EltwiseAdd) { - Tensor result = tf4in + tf4in; - - result.ToHost(); - const float* out = result.data<float>(); - - EXPECT_EQ(0.0f, out[0]); - EXPECT_EQ(2.0f, out[1]); - EXPECT_EQ(4.0f, out[2]); - EXPECT_EQ(6.0f, out[3]); - - result = tf4in + tf4zin; - - result.ToHost(); - const float* out1 = result.data<float>(); - - EXPECT_EQ(0.0f, out1[0]); - EXPECT_EQ(1.0f, out1[1]); - EXPECT_EQ(2.0f, out1[2]); - EXPECT_EQ(3.0f, out1[3]); - - result = Tensor(tf4in.shape(), tf4in.device(), tf4in.data_type()); - Add(tf4in, tf4in, &result); - - result.ToHost(); - const float* out2 = result.data<float>(); - - EXPECT_EQ(0.0f, out2[0]); - EXPECT_EQ(2.0f, out2[1]); - EXPECT_EQ(4.0f, out2[2]); - EXPECT_EQ(6.0f, out2[3]); - - result = tf4in + 1.0f; +TEST_F(OpenCL_TensorMath, MemberAddTensor) { + Tensor aa = a.Clone(); + aa += a; + aa.ToHost(); + const float *dptr = aa.data<float>(); + EXPECT_FLOAT_EQ(2.0f, dptr[0]); + EXPECT_FLOAT_EQ(4.0f, dptr[1]); + EXPECT_FLOAT_EQ(6.0f, dptr[2]); + + // check p is initialized to 0 + Tensor p(Shape{6}); + p += aa; + p.ToHost(); + const float *dptr1 = p.data<float>(); + EXPECT_FLOAT_EQ(2.0f, dptr1[0]); + EXPECT_FLOAT_EQ(4.0f, dptr1[1]); + EXPECT_FLOAT_EQ(6.0f, dptr1[2]); + + a += b; + a.ToHost(); + const float *dptr2 = a.data<float>(); + EXPECT_FLOAT_EQ(2.1f, dptr2[0]); + EXPECT_FLOAT_EQ(4.1f, dptr2[1]); + EXPECT_FLOAT_EQ(6.1f, dptr2[2]); + EXPECT_FLOAT_EQ(12.1f, dptr2[5]); +} - result.ToHost(); - const float* out3 = result.data<float>(); - EXPECT_EQ(1.0f, out3[0]); - EXPECT_EQ(2.0f, out3[1]); - EXPECT_EQ(3.0f, out3[2]); - EXPECT_EQ(4.0f, out3[3]); +TEST_F(OpenCL_TensorMath, AddTensors) { + Tensor ret(a.shape(), a.device(), a.data_type()); + Add(a, b, &ret); + ret.ToHost(); + const float *dptr = ret.data<float>(); + EXPECT_FLOAT_EQ(2.1f, dptr[0]); + EXPECT_FLOAT_EQ(4.1f, dptr[1]); + EXPECT_FLOAT_EQ(6.1f, dptr[2]); + EXPECT_FLOAT_EQ(12.1f, dptr[5]); + + Tensor d = a + b; + d.ToHost(); + const float *dptr2 = d.data<float>(); + EXPECT_FLOAT_EQ(2.1f, dptr2[0]); + EXPECT_FLOAT_EQ(4.1f, dptr2[1]); + EXPECT_FLOAT_EQ(6.1f, dptr2[2]); + EXPECT_FLOAT_EQ(12.1f, dptr2[5]); + + Add(a, b, &a); + a.ToHost(); + const float *dptr1 = a.data<float>(); + EXPECT_FLOAT_EQ(2.1f, dptr1[0]); + EXPECT_FLOAT_EQ(4.1f, dptr1[1]); + EXPECT_FLOAT_EQ(6.1f, dptr1[2]); + EXPECT_FLOAT_EQ(12.1f, dptr1[5]); } TEST_F(OpenCL_TensorMath, SetValue) { - const float one_third = 1.0f / 3.0f; - empty10k.SetValue(one_third); - - empty10k.ToHost(); - const float* out = empty10k.data<float>(); - - EXPECT_EQ(one_third, out[0]); - EXPECT_EQ(one_third, out[1]); - EXPECT_EQ(one_third, out[1024]); - EXPECT_EQ(one_third, out[4096]); - EXPECT_EQ(one_third, out[9998]); - EXPECT_EQ(one_third, out[9999]); + Tensor t(Shape{4}); + t.SetValue(0.3f); + t.ToHost(); + const float *ptr = t.data<float>(); + for (int i = 0; i < 4; i++) EXPECT_FLOAT_EQ(ptr[i], 0.3f); } TEST_F(OpenCL_TensorMath, Axpy) { - Axpy(10.0f, tf4in, &tf4in); - - tf4in.ToHost(); - const float* out = tf4in.data<float>(); - - EXPECT_EQ(0.0f, out[0]); // 0 * 10 + 0 = 0 - EXPECT_EQ(11.0f, out[1]); // 1 * 10 + 1 = 11 - EXPECT_EQ(22.0f, out[2]); // 2 * 10 + 2 = 22 - EXPECT_EQ(33.0f, out[3]); // 3 * 10 + 3 = 33 + Tensor ret(b.shape(), b.device(), b.data_type()); + const float zero[6] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + ret.CopyDataFromHostPtr<float>(zero, 6); + Axpy(10.0f, b, &ret); + ret.ToHost(); + const float* out = ret.data<float>(); + + EXPECT_EQ(11.0f, out[0]); // 1.1 * 10 + 0 = 11 + EXPECT_EQ(21.0f, out[1]); // 2.1 * 10 + 1 = 22 + EXPECT_EQ(31.0f, out[2]); // 3.1 * 10 + 2 = 33 + EXPECT_EQ(41.0f, out[3]); // 4.1 * 10 + 3 = 44 } -TEST_F(OpenCL_TensorMath, Mult) { - Tensor result = Mult(tf4in, tf4zin.T()); // Multiply with zero. +TEST_F(OpenCL_TensorMath, GEMM) { + a.Reshape(Shape{6, 1}); + Tensor result = Mult(a.T(), a); result.ToHost(); const float* out = result.data<float>(); - EXPECT_EQ(0.0f, out[0]); // 1x4 * 4x1 = 1x1. - - result = Mult(tf4in, tf4in.T()); - - result.ToHost(); - const float* out0 = result.data<float>(); - - EXPECT_EQ(14.0f, out0[0]); // 1x4 * 4x1 = 1x1. - - tf16zin.SetValue(10.0f); // Multiply with 10.0. - result = Mult(tf16in, tf16zin); // 4x4 * 4x4 = 4x4. - - result.ToHost(); - const float* out1 = result.data<float>(); - EXPECT_EQ(240.0f, out1[0]); - EXPECT_EQ(280.0f, out1[1]); - EXPECT_EQ(320.0f, out1[2]); - EXPECT_EQ(360.0f, out1[3]); - - EXPECT_EQ(240.0f, out1[4]); - EXPECT_EQ(280.0f, out1[5]); - EXPECT_EQ(320.0f, out1[6]); - EXPECT_EQ(360.0f, out1[7]); - - EXPECT_EQ(240.0f, out1[8]); - EXPECT_EQ(280.0f, out1[9]); - EXPECT_EQ(320.0f, out1[10]); - EXPECT_EQ(360.0f, out1[11]); - - EXPECT_EQ(240.0f, out1[12]); - EXPECT_EQ(280.0f, out1[13]); - EXPECT_EQ(320.0f, out1[14]); - EXPECT_EQ(360.0f, out1[15]); + EXPECT_EQ(91.0f, out[0]); } - // TODO: ComputeCrossEntropy, SoftmaxCrossEntropy // #endif // USE_OPENCL http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/595302a3/test/singa/test_opencl_device.cc ---------------------------------------------------------------------- diff --git a/test/singa/test_opencl_device.cc b/test/singa/test_opencl_device.cc new file mode 100644 index 0000000..2797a40 --- /dev/null +++ b/test/singa/test_opencl_device.cc @@ -0,0 +1,108 @@ +/************************************************************ +* +* 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 "gtest/gtest.h" +#include "singa/core/device.h" +#include "singa/proto/core.pb.h" + +#ifdef USE_OPENCL + +using singa::CppCPU; +using singa::OpenclDevice; +using singa::Block; + +TEST(OpenclDevice, Constructor) { + OpenclDevice dev; + EXPECT_EQ(0, dev.id()); +} + + +TEST(OpenclDevice, MemoryMallocFree) { + OpenclDevice dev; + Block* b = dev.NewBlock(4); + EXPECT_NE(nullptr, b); + EXPECT_EQ(4u, b->size()); + dev.FreeBlock(b); +} + + +TEST(OpenclDevice, Exec) { + OpenclDevice dev; + Block* b = dev.NewBlock(4); + int x = 1, y =3, z = 0; + dev.Exec([x, y, &z](singa::Context *ctx) { + z = x + y; + }, {b}, {b}, false); + EXPECT_EQ(x + y, z); + dev.FreeBlock(b); +} + +// Tests for integrity of one round of data transfer to an OpenCL device and back. +TEST(OpenclDevice, CopyDataToFrom) { + OpenclDevice dev; + CppCPU host; + + Block* a = host.NewBlock(4); + Block* b = dev.NewBlock(4); + Block* c = host.NewBlock(4); + + // Allocate the Block object on the host. + char s[] = {'a', 'b', 'c', 'x'}; + host.CopyDataFromHostPtr(a, s, 4); + + // Copy back and forth. + dev.CopyDataToFrom(b, a, 4, singa::kHostToDevice); + dev.CopyDataToFrom(c, b, 4, singa::kDeviceToHost); + + const char* astr = static_cast<const char*>(c->data()); + EXPECT_EQ('a', astr[0]); + EXPECT_EQ('b', astr[1]); + EXPECT_EQ('c', astr[2]); + EXPECT_EQ('x', astr[3]); +} + + +TEST(OpenclDevice, DuplicateDataOnDevice) { + OpenclDevice dev; + CppCPU host; + + Block* a = host.NewBlock(4); + Block* b = dev.NewBlock(4); + Block* c = dev.NewBlock(4); + Block* d = host.NewBlock(4); + + // Allocate the Block object on the host. + char s[] = {'a', 'b', 'c', 'x'}; + host.CopyDataFromHostPtr(a, s, 4); + + // Copy to device and duplicate. + dev.CopyDataToFrom(b, a, 4, singa::kHostToDevice); + dev.CopyDataToFrom(c, b, 4, singa::kDeviceToDevice); + dev.CopyDataToFrom(d, c, 4, singa::kDeviceToHost); + + const char* astr = static_cast<const char*>(d->data()); + EXPECT_EQ('a', astr[0]); + EXPECT_EQ('b', astr[1]); + EXPECT_EQ('c', astr[2]); + EXPECT_EQ('x', astr[3]); +} + +#endif // USE_OPENCL
