SkelCL
SkelCL is a high level multi GPU skeleton library developed at the university of Münster, Germany.
 All Classes Namespaces Files Functions Variables Typedefs Groups
MapTests.cpp
1 /*****************************************************************************
2  * Copyright (c) 2011-2012 The SkelCL Team as listed in CREDITS.txt *
3  * http://skelcl.uni-muenster.de *
4  * *
5  * This file is part of SkelCL. *
6  * SkelCL is available under multiple licenses. *
7  * The different licenses are subject to terms and condition as provided *
8  * in the files specifying the license. See "LICENSE.txt" for details *
9  * *
10  *****************************************************************************
11  * *
12  * SkelCL is free software: you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation, either version 3 of the License, or *
15  * (at your option) any later version. See "LICENSE-gpl.txt" for details. *
16  * *
17  * SkelCL is distributed in the hope that it will be useful, *
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20  * GNU General Public License for more details. *
21  * *
22  *****************************************************************************
23  * *
24  * For non-commercial academic use see the license specified in the file *
25  * "LICENSE-academic.txt". *
26  * *
27  *****************************************************************************
28  * *
29  * If you are interested in other licensing models, including a commercial- *
30  * license, please contact the author at michel.steuwer@uni-muenster.de *
31  * *
32  *****************************************************************************/
33 
37 
38 #include <fstream>
39 
40 #include <cstdio>
41 
42 #include <pvsutil/Logger.h>
43 
44 #include <SkelCL/SkelCL.h>
45 #include <SkelCL/Matrix.h>
46 #include <SkelCL/Vector.h>
47 #include <SkelCL/Map.h>
48 
49 #include "Test.h"
52 
53 class MapTest : public ::testing::Test {
54 protected:
55  MapTest() {
56  //pvsutil::defaultLogger.setLoggingLevel(
57  // pvsutil::Logger::Severity::DebugInfo );
58 
60  }
61 
62  ~MapTest() {
64  }
65 };
66 
67 TEST_F(MapTest, CreateMapWithString) {
68  skelcl::Map<float(float)> m{"float func(float f){ return -f; }"};
69 }
70 
71 TEST_F(MapTest, CreateMapWithFile) {
72  std::string filename{ "TestFunction.cl" };
73  {
74  std::ofstream file{ filename, std::ios_base::trunc };
75  file << "float func(float f) { return -f; }";
76  }
77  std::ifstream file{ filename };
78 
79  skelcl::Map<float(float)> m{ file };
80 
81  remove(filename.c_str()); // delete file
82 }
83 
84 TEST_F(MapTest, CreateMapWithFileII) {
85  std::string filename{ "TestFunction.cl" };
86  {
87  std::ofstream file{ filename, std::ios_base::trunc };
88  file << "float func(float f) { return -f; }";
89  }
90 
91  skelcl::Map<float(float)> m{ std::ifstream{ filename } };
92 
93  remove(filename.c_str()); // delete file
94 }
95 
96 TEST_F(MapTest, SimpleMap) {
97  skelcl::Map<float(float)> m{ "float func(float f){ return -f; }" };
98 
99  skelcl::Vector<float> input(10);
100  for (size_t i = 0; i < input.size(); ++i) {
101  input[i] = i * 2.5f;
102  }
103  EXPECT_EQ(10, input.size());
104 
105  skelcl::Vector<float> output = m(input);
106 
107  EXPECT_EQ(10, output.size());
108  for (size_t i = 0; i < output.size(); ++i) {
109  EXPECT_EQ(-input[i], output[i]);
110  }
111 }
112 
113 TEST_F(MapTest, SimpleMultiDeviceMap) {
116  skelcl::Map<float(float)> m{ "float func(float f){ return -f; }" };
117 
118  skelcl::Vector<float> input(10);
119  for (size_t i = 0; i < input.size(); ++i) {
120  input[i] = i * 2.5f;
121  }
122  EXPECT_EQ(10, input.size());
123 
124  skelcl::Vector<float> output(input.size());
125  m(skelcl::out(output), input);
126 
127  EXPECT_EQ(10, output.size());
128  for (size_t i = 0; i < output.size(); ++i) {
129  EXPECT_EQ(-input[i], output[i]);
130  }
131 }
132 
133 TEST_F(MapTest, SimpleMultiDeviceMap2) {
136  skelcl::Map<int(float)> m{ "int func(float f) \
137  { return skelcl_get_device_id(); }" };
138 
139  skelcl::Vector<float> input(10);
140  EXPECT_EQ(10, input.size());
141 
142  skelcl::Vector<int> output = m(input);
143 
144  EXPECT_EQ(10, output.size());
145  for (size_t i = 0; i < output.size(); ++i) {
146  if (skelcl::detail::globalDeviceList.size() == 2) {
147  if (i < 5) {
148  EXPECT_EQ(0, output[i]);
149  } else {
150  EXPECT_EQ(1, output[i]);
151  }
152  } else {
153  EXPECT_EQ(0, output[i]);
154  }
155  }
156 }
157 
158 TEST_F(MapTest, AddArgs) {
159  skelcl::Map<float(float)> m{ "float func(float f, float add, float add2)\
160  { return f+add+add2; }" };
161 
162  skelcl::Vector<float> input(10);
163  for (size_t i = 0; i < input.size(); ++i) {
164  input[i] = i * 2.5f;
165  }
166  EXPECT_EQ(10, input.size());
167 
168  float add = 5.25f;
169  float add2 = 7.75f;
170 
171  skelcl::Vector<float> output = m(input, add, add2);
172 
173  EXPECT_EQ(10, output.size());
174  for (size_t i = 0; i < output.size(); ++i) {
175  EXPECT_EQ(input[i]+add+add2, output[i]);
176  }
177 }
178 
179 TEST_F(MapTest, MapVoid) {
180  skelcl::Map<void(float)> m{ "void func(float f, __global float* out) \
181  { out[get_global_id(0)] = f; }" };
182 
183  skelcl::Vector<float> input(10);
184  for (size_t i = 0; i < input.size(); ++i) {
185  input[i] = i * 2.5f;
186  }
187  EXPECT_EQ(10, input.size());
188 
189  skelcl::Vector<float> output(10);
190  m(input, skelcl::out(output));
191 
192  for (size_t i = 0; i < output.size(); ++i) {
193  EXPECT_EQ(input[i], output[i]);
194  }
195 }
196 
197 skelcl::Vector<float> execute(const skelcl::Vector<float>& input)
198 {
199  skelcl::Map<float(float)> m{ "float func(float f) { return -f; }" };
200  // tmp should not be destroyed right away
201  // the computation must finish first
202  skelcl::Vector<float> tmp{ input };
203  return m(tmp);
204 }
205 
206 #if 0
207 // currently not working with nvidia opencl implementation
208 TEST_F(MapTest, TempInputVector) {
209  auto size = 1024 * 1000;
210  skelcl::Vector<float> output;
211  skelcl::Vector<float> input(size);
212  for (size_t i = 0; i < input.size(); ++i) {
213  input[i] = i * 2.5f;
214  }
215  EXPECT_EQ(size, input.size());
216 
217  output = execute(input);
218 
219  for (size_t i = 0; i < output.size(); ++i) {
220  EXPECT_EQ(-input[i], output[i]);
221  }
222 }
223 #endif
224 
225 TEST_F(MapTest, SimpleMap2D) {
226  skelcl::Map<float(float)> m("float func(float f){ return -f; }");
227 
228  std::vector<float> vec(10);
229  for (size_t i = 0; i < vec.size(); ++i) {
230  vec[i] = static_cast<float>(i);
231  }
232 
233  skelcl::Matrix<float> input(vec, 3);
234  EXPECT_EQ(skelcl::Matrix<float>::size_type(4,3), input.size());
235 
236  skelcl::Matrix<float> output = m(input);
237 
238  EXPECT_EQ(input.size(), output.size());
239 
240  for (size_t i = 0; i < output.rowCount(); ++i) {
241  for(size_t j = 0; j < output.columnCount(); ++j) {
242  EXPECT_EQ(-input({i,j}), output({i,j}));
243  EXPECT_EQ(-input[i][j], output[i][j]);
244  }
245  }
246 }
247 
248 TEST_F(MapTest, MatrixAddArgs) {
249  skelcl::Map<float(float)> m(
250  "float func(float f, float add, float add2) { return f+add+add2; }");
251 
252  std::vector<float> vec(10);
253  for (size_t i = 0; i < 10; ++i) {
254  vec[i] = static_cast<float>(i*2.5f);
255  }
256 
257  skelcl::Matrix<float> input(vec,3);
258  EXPECT_EQ(skelcl::Matrix<float>::size_type(4,3), input.size());
259 
260  float add = 5.25f;
261  float add2 = 7.75f;
262 
263  skelcl::Matrix<float> output = m(input, add, add2);
264 
265  EXPECT_EQ(input.size(), output.size());
266 
267  for (size_t i = 0; i < output.rowCount(); ++i) {
268  for (size_t j = 0; j < output.columnCount(); ++j) {
269  EXPECT_EQ(input({i,j})+add+add2, output({i,j}));
270  }
271  }
272 }
273 
274 TEST_F(MapTest, MatrixAddArgsMatrix) {
275 #if 0
276  // old way
277  skelcl::Map<float(float)> m(R"(
278 float func( float f,__global float* mat, uint mat_col_count, float add2)
279 {
280  return f + get(mat, 1, 1) + add2;
281 }
282 )");
283 #endif
284  skelcl::Map<float(float)> m(R"(
285 float func( float f, float_matrix_t mat, float add2, int_matrix_t mat2 )
286 {
287  return f + get(mat, 1, 1) + add2 + get(mat2, 1, 2);
288 }
289 )");
290 
291  std::vector<float> vec(10);
292  for (size_t i = 0; i < 10; ++i) {
293  vec[i] = static_cast<float>(i * 2.5f);
294  }
295 
296  skelcl::Matrix<float> input(vec,3);
297  EXPECT_EQ(skelcl::Matrix<float>::size_type(4,3), input.size());
298 
299  std::vector<float> vec2(10);
300  for (size_t i = 0; i < 10; ++i) {
301  vec[i] = static_cast<float>(i);
302  }
303 
304  skelcl::Matrix<float> mat(vec2, 3);
305  EXPECT_EQ(skelcl::Matrix<float>::size_type(4,3), mat.size());
306 
307  skelcl::Matrix<int> mat2( {2,3} );
308  mat2[1][2] = 5;
309 
310  float add2 = 7.75f;
311 
312  skelcl::Matrix<float> output = m(input, mat, add2, mat2);
313 
314  EXPECT_EQ(input.size(), output.size());
315 
316  for (size_t i = 0; i < output.rowCount(); ++i) {
317  for(size_t j = 0; j < output.columnCount(); ++j) {
318  EXPECT_EQ(input[i][j]+mat({1,1})+add2+mat2[1][2], output[i][j]);
319  }
320  }
321 }
322 
323 TEST_F(MapTest, MapWithSingleDistribution0) {
325  skelcl::init();
326 
327  skelcl::Map<int(int)> map{"int func(int i) { return -i; }"};
328  skelcl::Vector<int> input(10);
330 
331  skelcl::Vector<int> output = map(input);
332 }
333 
334 TEST_F(MapTest, MapWithSingleDistribution1) {
336  skelcl::init();
337 
338  if (skelcl::detail::globalDeviceList.size() > 1) {
339  skelcl::Map<int(int)> map{"int func(int i) { return -i; }"};
340  skelcl::Vector<int> input(10);
341  auto dev = ++(skelcl::detail::globalDeviceList.begin());
342  skelcl::distribution::setSingle(input, *dev);
343 
344  skelcl::Vector<int> output = map(input);
345  }
346 }
347 
348 TEST_F(MapTest, MapWithLocalMemory) {
349  // Important for usage of skelcl::Local :
350  // input vector size must be multiple of workGroupSize to use barrier()!
351 
352  skelcl::Map<int(int)> map{"int func(int i, __local int* lp) \
353  { lp[0] = i; barrier(CLK_LOCAL_MEM_FENCE); return -lp[0]; }"};
354 
355  map.setWorkGroupSize(16);
356  skelcl::Vector<int> input(32);
357  for (size_t i = 0; i < input.size(); ++i) {
358  input[i] = 5;
359  }
360 
361  skelcl::Vector<int> output = map(input, skelcl::Local(sizeof(int)));
362  for (size_t i = 0; i < output.size(); ++i) {
363  EXPECT_EQ(-input[i], output[i]);
364  }
365 }
366 
367 TEST_F(MapTest, MapFloat4) {
368  skelcl::Map<skelcl::float4(skelcl::float4)>
369  m {"float4 func(float4 f) { return -f; }"};
370 
372  for (size_t i = 0; i < input.size(); ++i) {
373  input[i].s0 = 1.0f;
374  input[i].s1 = 2.0f;
375  input[i].s2 = 3.0f;
376  input[i].s3 = 4.0f;
377  }
378 
379  skelcl::Vector<skelcl::float4> output = m(input);
380 
381  EXPECT_EQ(input.size(), output.size());
382  for (size_t i = 0; i < output.size(); ++i) {
383  EXPECT_EQ(-input[i].s0, output[i].s0);
384  EXPECT_EQ(-input[i].s1, output[i].s1);
385  EXPECT_EQ(-input[i].s2, output[i].s2);
386  EXPECT_EQ(-input[i].s3, output[i].s3);
387  }
388 }
389 
390 TEST_F(MapTest, MapDouble4) {
391  auto& devPtr = skelcl::detail::globalDeviceList.front();
392  if (devPtr->supportsDouble()) {
393 
394  skelcl::Map<skelcl::double4(skelcl::double4)>
395  m {"double4 func(double4 f) { return -f; }"};
396 
398  for (size_t i = 0; i < input.size(); ++i) {
399  input[i].s0 = 1.0;
400  input[i].s1 = 2.0;
401  input[i].s2 = 3.0;
402  input[i].s3 = 4.0;
403  }
404 
405  skelcl::Vector<skelcl::double4> output = m(input);
406 
407  EXPECT_EQ(input.size(), output.size());
408  for (size_t i = 0; i < output.size(); ++i) {
409  EXPECT_EQ(-input[i].s0, output[i].s0);
410  EXPECT_EQ(-input[i].s1, output[i].s1);
411  EXPECT_EQ(-input[i].s2, output[i].s2);
412  EXPECT_EQ(-input[i].s3, output[i].s3);
413  }
414  }
415 }
416 
418 
The Matrix class is a two dimensional container which makes its data accessible on the host as well a...
Definition: Matrix.h:190
Out< ContainerType< T > > out(ContainerType< T > &c)
Helper function to create a Out wrapper object.
Definition: Out.h:94
size_type size() const
Returns the number of elements in the Vector.
void setSingle(const C< T > &c)
This function sets the distribution of the given container to the SingleDistribution using the defaul...
SKELCL_DLL void init(detail::DeviceProperties properties=allDevices())
Initializes the SkelCL library. This function (or another init function) has to be called prior to ev...
Definition: SkelCL.cpp:51
SKELCL_DLL detail::DeviceProperties nDevices(size_t n)
Creates a detail::DeviceProperties object representing n devices. This object should be used as param...
Definition: SkelCL.cpp:66
The Vector class is a one dimensional container which makes its data accessible on the host as well a...
Definition: Vector.h:113
This class defines a two dimensional size for a Matrix.
Definition: Matrix.h:67
SKELCL_DLL void terminate()
Frees all resources allocated internally by SkelCL.
Definition: SkelCL.cpp:81
This class represents OpenCL local memory in SkelCL.
Definition: Local.h:58