1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2016
5 // Mehdi Goli Codeplay Software Ltd.
6 // Ralph Potter Codeplay Software Ltd.
7 // Luke Iwanski Codeplay Software Ltd.
8 // Contact: <eigen@codeplay.com>
9 //
10 // This Source Code Form is subject to the terms of the Mozilla
11 // Public License v. 2.0. If a copy of the MPL was not distributed
12 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
13
14 #define EIGEN_TEST_NO_LONGDOUBLE
15 #define EIGEN_TEST_NO_COMPLEX
16
17 #define EIGEN_DEFAULT_DENSE_INDEX_TYPE int64_t
18 #define EIGEN_USE_SYCL
19 static const float error_threshold =1e-8f;
20
21 #include "main.h"
22 #include <unsupported/Eigen/CXX11/Tensor>
23
24 using Eigen::Tensor;
25 struct Generator1D {
Generator1DGenerator1D26 Generator1D() { }
27
operator ()Generator1D28 float operator()(const array<Eigen::DenseIndex, 1>& coordinates) const {
29 return coordinates[0];
30 }
31 };
32
33 template <typename DataType, int DataLayout, typename IndexType>
test_1D_sycl(const Eigen::SyclDevice & sycl_device)34 static void test_1D_sycl(const Eigen::SyclDevice& sycl_device)
35 {
36
37 IndexType sizeDim1 = 6;
38 array<IndexType, 1> tensorRange = {{sizeDim1}};
39 Tensor<DataType, 1, DataLayout,IndexType> vec(tensorRange);
40 Tensor<DataType, 1, DataLayout,IndexType> result(tensorRange);
41
42 const size_t tensorBuffSize =vec.size()*sizeof(DataType);
43 DataType* gpu_data_vec = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
44 DataType* gpu_data_result = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
45
46 TensorMap<Tensor<DataType, 1, DataLayout,IndexType>> gpu_vec(gpu_data_vec, tensorRange);
47 TensorMap<Tensor<DataType, 1, DataLayout,IndexType>> gpu_result(gpu_data_result, tensorRange);
48
49 sycl_device.memcpyHostToDevice(gpu_data_vec, vec.data(), tensorBuffSize);
50 gpu_result.device(sycl_device)=gpu_vec.generate(Generator1D());
51 sycl_device.memcpyDeviceToHost(result.data(), gpu_data_result, tensorBuffSize);
52
53 for (IndexType i = 0; i < 6; ++i) {
54 VERIFY_IS_EQUAL(result(i), i);
55 }
56 }
57
58
59 struct Generator2D {
Generator2DGenerator2D60 Generator2D() { }
61
operator ()Generator2D62 float operator()(const array<Eigen::DenseIndex, 2>& coordinates) const {
63 return 3 * coordinates[0] + 11 * coordinates[1];
64 }
65 };
66
67 template <typename DataType, int DataLayout, typename IndexType>
test_2D_sycl(const Eigen::SyclDevice & sycl_device)68 static void test_2D_sycl(const Eigen::SyclDevice& sycl_device)
69 {
70 IndexType sizeDim1 = 5;
71 IndexType sizeDim2 = 7;
72 array<IndexType, 2> tensorRange = {{sizeDim1, sizeDim2}};
73 Tensor<DataType, 2, DataLayout,IndexType> matrix(tensorRange);
74 Tensor<DataType, 2, DataLayout,IndexType> result(tensorRange);
75
76 const size_t tensorBuffSize =matrix.size()*sizeof(DataType);
77 DataType* gpu_data_matrix = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
78 DataType* gpu_data_result = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
79
80 TensorMap<Tensor<DataType, 2, DataLayout,IndexType>> gpu_matrix(gpu_data_matrix, tensorRange);
81 TensorMap<Tensor<DataType, 2, DataLayout,IndexType>> gpu_result(gpu_data_result, tensorRange);
82
83 sycl_device.memcpyHostToDevice(gpu_data_matrix, matrix.data(), tensorBuffSize);
84 gpu_result.device(sycl_device)=gpu_matrix.generate(Generator2D());
85 sycl_device.memcpyDeviceToHost(result.data(), gpu_data_result, tensorBuffSize);
86
87 for (IndexType i = 0; i < 5; ++i) {
88 for (IndexType j = 0; j < 5; ++j) {
89 VERIFY_IS_EQUAL(result(i, j), 3*i + 11*j);
90 }
91 }
92 }
93
94 template <typename DataType, int DataLayout, typename IndexType>
test_gaussian_sycl(const Eigen::SyclDevice & sycl_device)95 static void test_gaussian_sycl(const Eigen::SyclDevice& sycl_device)
96 {
97 IndexType rows = 32;
98 IndexType cols = 48;
99 array<DataType, 2> means;
100 means[0] = rows / 2.0f;
101 means[1] = cols / 2.0f;
102 array<DataType, 2> std_devs;
103 std_devs[0] = 3.14f;
104 std_devs[1] = 2.7f;
105 internal::GaussianGenerator<DataType, Eigen::DenseIndex, 2> gaussian_gen(means, std_devs);
106
107 array<IndexType, 2> tensorRange = {{rows, cols}};
108 Tensor<DataType, 2, DataLayout,IndexType> matrix(tensorRange);
109 Tensor<DataType, 2, DataLayout,IndexType> result(tensorRange);
110
111 const size_t tensorBuffSize =matrix.size()*sizeof(DataType);
112 DataType* gpu_data_matrix = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
113 DataType* gpu_data_result = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
114
115 TensorMap<Tensor<DataType, 2, DataLayout,IndexType>> gpu_matrix(gpu_data_matrix, tensorRange);
116 TensorMap<Tensor<DataType, 2, DataLayout,IndexType>> gpu_result(gpu_data_result, tensorRange);
117
118 sycl_device.memcpyHostToDevice(gpu_data_matrix, matrix.data(), tensorBuffSize);
119 gpu_result.device(sycl_device)=gpu_matrix.generate(gaussian_gen);
120 sycl_device.memcpyDeviceToHost(result.data(), gpu_data_result, tensorBuffSize);
121
122 for (IndexType i = 0; i < rows; ++i) {
123 for (IndexType j = 0; j < cols; ++j) {
124 DataType g_rows = powf(rows/2.0f - i, 2) / (3.14f * 3.14f) * 0.5f;
125 DataType g_cols = powf(cols/2.0f - j, 2) / (2.7f * 2.7f) * 0.5f;
126 DataType gaussian = expf(-g_rows - g_cols);
127 Eigen::internal::isApprox(result(i, j), gaussian, error_threshold);
128 }
129 }
130 }
131
sycl_generator_test_per_device(dev_Selector s)132 template<typename DataType, typename dev_Selector> void sycl_generator_test_per_device(dev_Selector s){
133 QueueInterface queueInterface(s);
134 auto sycl_device = Eigen::SyclDevice(&queueInterface);
135 test_1D_sycl<DataType, RowMajor, int64_t>(sycl_device);
136 test_1D_sycl<DataType, ColMajor, int64_t>(sycl_device);
137 test_2D_sycl<DataType, RowMajor, int64_t>(sycl_device);
138 test_2D_sycl<DataType, ColMajor, int64_t>(sycl_device);
139 test_gaussian_sycl<DataType, RowMajor, int64_t>(sycl_device);
140 test_gaussian_sycl<DataType, ColMajor, int64_t>(sycl_device);
141 }
EIGEN_DECLARE_TEST(cxx11_tensor_generator_sycl)142 EIGEN_DECLARE_TEST(cxx11_tensor_generator_sycl)
143 {
144 for (const auto& device :Eigen::get_sycl_supported_devices()) {
145 CALL_SUBTEST(sycl_generator_test_per_device<float>(device));
146 }
147 }
148