| 1 | #include <cmath> |
|---|
| 2 | #include <typeinfo> |
|---|
| 3 | // #include <CL/cl.h> |
|---|
| 4 | #include <iostream> |
|---|
| 5 | #include <emmintrin.h> |
|---|
| 6 | // #include <pmmintrin.h> |
|---|
| 7 | #include <sys/time.h> |
|---|
| 8 | #include <vector> |
|---|
| 9 | #include <libgeodecomp/misc/grid.h> |
|---|
| 10 | |
|---|
| 11 | using namespace LibGeoDecomp; |
|---|
| 12 | |
|---|
| 13 | class Scalar2D |
|---|
| 14 | { |
|---|
| 15 | public: |
|---|
| 16 | static int coefficients() |
|---|
| 17 | { |
|---|
| 18 | return 0; |
|---|
| 19 | } |
|---|
| 20 | |
|---|
| 21 | inline void step(double *src, double *dst, int offset, int startX, int endX) |
|---|
| 22 | { |
|---|
| 23 | for (int x = startX; x < endX; ++x) { |
|---|
| 24 | dst[x] = (src[x - offset] + src[x - 1] + src[x] + src[x + 1] + src[x + offset]) * 0.2; |
|---|
| 25 | } |
|---|
| 26 | } |
|---|
| 27 | |
|---|
| 28 | int flops() |
|---|
| 29 | { |
|---|
| 30 | return 5; |
|---|
| 31 | } |
|---|
| 32 | }; |
|---|
| 33 | |
|---|
| 34 | class VectorizedSSEMelbourneShuffle2D |
|---|
| 35 | { |
|---|
| 36 | public: |
|---|
| 37 | static int coefficients() |
|---|
| 38 | { |
|---|
| 39 | return 0; |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | inline void step(double *src, double *dst, int offset, int startX, int endX) |
|---|
| 43 | { |
|---|
| 44 | int x = startX; |
|---|
| 45 | Scalar2D scalarUpdater; |
|---|
| 46 | |
|---|
| 47 | if ((x & 1) == 1) { |
|---|
| 48 | scalarUpdater.step(src, dst, offset, x, x + 1); |
|---|
| 49 | x += 1; |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | __m128d oneFifth = _mm_set_pd(1.0/3.0, 1.0/3.0); |
|---|
| 53 | __m128d buff0 = _mm_loadu_pd(src + x - 1); |
|---|
| 54 | __m128d same0 = _mm_load_pd(src + x + 0); |
|---|
| 55 | |
|---|
| 56 | int paddedEndX = endX - 7; |
|---|
| 57 | for (; x < paddedEndX; x += 8) { |
|---|
| 58 | // load center row |
|---|
| 59 | __m128d same1 = _mm_load_pd(src + x + 2); |
|---|
| 60 | __m128d same2 = _mm_load_pd(src + x + 4); |
|---|
| 61 | __m128d same3 = _mm_load_pd(src + x + 6); |
|---|
| 62 | __m128d same4 = _mm_load_pd(src + x + 8); |
|---|
| 63 | |
|---|
| 64 | // shuffle values obtain left/right neighbors |
|---|
| 65 | __m128d buff1 = _mm_shuffle_pd(same0, same1, (1 << 0) | (0 << 2)); |
|---|
| 66 | __m128d buff2 = _mm_shuffle_pd(same1, same2, (1 << 0) | (0 << 2)); |
|---|
| 67 | __m128d buff3 = _mm_shuffle_pd(same2, same3, (1 << 0) | (0 << 2)); |
|---|
| 68 | __m128d buff4 = _mm_shuffle_pd(same3, same4, (1 << 0) | (0 << 2)); |
|---|
| 69 | |
|---|
| 70 | // load top row |
|---|
| 71 | __m128d temp0 = _mm_load_pd(src - offset + x + 0); |
|---|
| 72 | __m128d temp1 = _mm_load_pd(src - offset + x + 2); |
|---|
| 73 | __m128d temp2 = _mm_load_pd(src - offset + x + 4); |
|---|
| 74 | __m128d temp3 = _mm_load_pd(src - offset + x + 6); |
|---|
| 75 | |
|---|
| 76 | // add center row with left... |
|---|
| 77 | same0 = _mm_add_pd(same0, buff0); |
|---|
| 78 | same1 = _mm_add_pd(same1, buff1); |
|---|
| 79 | same2 = _mm_add_pd(same2, buff2); |
|---|
| 80 | same3 = _mm_add_pd(same3, buff3); |
|---|
| 81 | |
|---|
| 82 | // ...and right neighbors |
|---|
| 83 | same0 = _mm_add_pd(same0, buff1); |
|---|
| 84 | same1 = _mm_add_pd(same1, buff2); |
|---|
| 85 | same2 = _mm_add_pd(same2, buff3); |
|---|
| 86 | same3 = _mm_add_pd(same3, buff4); |
|---|
| 87 | |
|---|
| 88 | // load bottom row |
|---|
| 89 | buff0 = _mm_load_pd(src + offset + x + 0); |
|---|
| 90 | buff1 = _mm_load_pd(src + offset + x + 2); |
|---|
| 91 | buff2 = _mm_load_pd(src + offset + x + 4); |
|---|
| 92 | buff3 = _mm_load_pd(src + offset + x + 6); |
|---|
| 93 | |
|---|
| 94 | // add top row |
|---|
| 95 | same0 = _mm_add_pd(same0, temp0); |
|---|
| 96 | same1 = _mm_add_pd(same1, temp1); |
|---|
| 97 | same2 = _mm_add_pd(same2, temp2); |
|---|
| 98 | same3 = _mm_add_pd(same3, temp3); |
|---|
| 99 | |
|---|
| 100 | // add bottom row |
|---|
| 101 | same0 = _mm_add_pd(same0, buff0); |
|---|
| 102 | same1 = _mm_add_pd(same1, buff1); |
|---|
| 103 | same2 = _mm_add_pd(same2, buff2); |
|---|
| 104 | same3 = _mm_add_pd(same3, buff3); |
|---|
| 105 | |
|---|
| 106 | // scale down... |
|---|
| 107 | same0 = _mm_mul_pd(same0, oneFifth); |
|---|
| 108 | same1 = _mm_mul_pd(same1, oneFifth); |
|---|
| 109 | same2 = _mm_mul_pd(same2, oneFifth); |
|---|
| 110 | same3 = _mm_mul_pd(same3, oneFifth); |
|---|
| 111 | |
|---|
| 112 | // ...and store |
|---|
| 113 | _mm_store_pd(dst + 0, same0); |
|---|
| 114 | _mm_store_pd(dst + 2, same1); |
|---|
| 115 | _mm_store_pd(dst + 4, same2); |
|---|
| 116 | _mm_store_pd(dst + 6, same3); |
|---|
| 117 | |
|---|
| 118 | same0 = same4; |
|---|
| 119 | buff0 = buff4; |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | scalarUpdater.step(src, dst, offset, x, endX); |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | int flops() |
|---|
| 126 | { |
|---|
| 127 | return 5; |
|---|
| 128 | } |
|---|
| 129 | }; |
|---|
| 130 | |
|---|
| 131 | |
|---|
| 132 | template<typename UPDATER, int DIM> |
|---|
| 133 | class Benchmark |
|---|
| 134 | { |
|---|
| 135 | public: |
|---|
| 136 | typedef Grid<double, typename Topologies::Cube<DIM>::Topology> GridType; |
|---|
| 137 | |
|---|
| 138 | |
|---|
| 139 | void run(Coord<DIM> dim, int repeats) |
|---|
| 140 | { |
|---|
| 141 | Coord<DIM> coeffDim = dim; |
|---|
| 142 | coeffDim.c[DIM - 1] *= UPDATER::coefficients(); |
|---|
| 143 | GridType coeff(coeffDim, 0.1); |
|---|
| 144 | GridType a(dim, 1.0); |
|---|
| 145 | GridType b(dim, 1.0); |
|---|
| 146 | |
|---|
| 147 | GridType *oldGrid = &a; |
|---|
| 148 | GridType *newGrid = &b; |
|---|
| 149 | |
|---|
| 150 | UPDATER updater; |
|---|
| 151 | |
|---|
| 152 | long long tStart = getUTtime(); |
|---|
| 153 | std::vector<double*> coefficients(UPDATER::coefficients()); |
|---|
| 154 | |
|---|
| 155 | for (int t = 0; t < repeats; ++t) { |
|---|
| 156 | for (int z = 1; z < dim.c[2] - 1; ++z) { |
|---|
| 157 | for (int y = 1; y < dim.c[1] - 1; ++y) { |
|---|
| 158 | Coord<DIM> c(0, y, z); |
|---|
| 159 | Coord<DIM> coeffCoord = c; |
|---|
| 160 | for (int i = 0; i < UPDATER::coefficients(); ++i) { |
|---|
| 161 | coefficients[i] = &coeff.at(coeffCoord); |
|---|
| 162 | coeffCoord.c[DIM - 1] += dim.c[DIM - 1]; |
|---|
| 163 | } |
|---|
| 164 | updater.step(&coefficients[0], &oldGrid->at(c), &newGrid->at(c), dim.c[1], dim.c[2], 1, dim.c[0] - 1); |
|---|
| 165 | } |
|---|
| 166 | } |
|---|
| 167 | std::swap(newGrid, oldGrid); |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | long long tEnd = getUTtime(); |
|---|
| 171 | evaluate(dim, repeats, tEnd - tStart); |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | void exercise() |
|---|
| 175 | { |
|---|
| 176 | std::cout << "# " << typeid(UPDATER).name() << "\n"; |
|---|
| 177 | int lastDim = 0; |
|---|
| 178 | for (int i = 4; i <= 4096; i *= 2) { |
|---|
| 179 | int intermediateSteps = 8; |
|---|
| 180 | for (int j = 0; j < intermediateSteps; ++j) { |
|---|
| 181 | int d = i * std::pow(2, j * (1.0 / intermediateSteps)); |
|---|
| 182 | if (d % 2) { |
|---|
| 183 | d += 1; |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | if (d > lastDim) { |
|---|
| 187 | lastDim = d; |
|---|
| 188 | Coord<DIM> dim; |
|---|
| 189 | for (int i = 0; i < DIM; ++i) |
|---|
| 190 | dim.c[i] = d; |
|---|
| 191 | int repeats = std::max(1, 10000000 / dim.prod()); |
|---|
| 192 | run(dim, repeats); |
|---|
| 193 | } |
|---|
| 194 | } |
|---|
| 195 | } |
|---|
| 196 | std::cout << "\n"; |
|---|
| 197 | } |
|---|
| 198 | |
|---|
| 199 | private: |
|---|
| 200 | long long getUTtime() |
|---|
| 201 | { |
|---|
| 202 | timeval t; |
|---|
| 203 | gettimeofday(&t, 0); |
|---|
| 204 | return (long long)t.tv_sec * 1000000 + t.tv_usec; |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | void evaluate(Coord<DIM> dim, int repeats, long long uTime) |
|---|
| 208 | { |
|---|
| 209 | double seconds = 1.0 * uTime / 1000 / 1000; |
|---|
| 210 | Coord<DIM> inner = dim; |
|---|
| 211 | for (int i = 0; i < DIM; ++i) |
|---|
| 212 | inner.c[i] -= 2; |
|---|
| 213 | double gflops = 1.0 * UPDATER().flops() * inner.prod() * |
|---|
| 214 | repeats / 1000 / 1000 / 1000 / seconds; |
|---|
| 215 | std::cout << dim.x() << " " << gflops << "\n"; |
|---|
| 216 | } |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | }; |
|---|
| 220 | |
|---|
| 221 | class Scalar3D |
|---|
| 222 | { |
|---|
| 223 | public: |
|---|
| 224 | static int coefficients() |
|---|
| 225 | { |
|---|
| 226 | return 7; |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | inline void step(double *coeff[7], double *src, double *dst, int offsetY, int offsetZ, int startX, int endX) |
|---|
| 230 | { |
|---|
| 231 | for (int x = startX; x < endX; ++x) { |
|---|
| 232 | dst[x] = |
|---|
| 233 | coeff[0][x] * src[x - offsetZ] + |
|---|
| 234 | coeff[1][x] * src[x - offsetY] + |
|---|
| 235 | coeff[2][x] * src[x - 1] + |
|---|
| 236 | coeff[3][x] * src[x] + |
|---|
| 237 | coeff[4][x] * src[x + 1] + |
|---|
| 238 | coeff[5][x] * src[x + offsetY] + |
|---|
| 239 | coeff[6][x] * src[x + offsetZ]; |
|---|
| 240 | } |
|---|
| 241 | } |
|---|
| 242 | |
|---|
| 243 | int flops() |
|---|
| 244 | { |
|---|
| 245 | return 13; |
|---|
| 246 | } |
|---|
| 247 | }; |
|---|
| 248 | |
|---|
| 249 | class Vectorized3D |
|---|
| 250 | { |
|---|
| 251 | public: |
|---|
| 252 | static int coefficients() |
|---|
| 253 | { |
|---|
| 254 | return 7; |
|---|
| 255 | } |
|---|
| 256 | |
|---|
| 257 | inline void step(double **coeff, double *src, double *dst, int offsetY, int offsetZ, int startX, int endX) |
|---|
| 258 | { |
|---|
| 259 | int x = startX; |
|---|
| 260 | Scalar3D scalarUpdater; |
|---|
| 261 | |
|---|
| 262 | if ((x & 1) == 1) { |
|---|
| 263 | scalarUpdater.step(coeff, src, dst, offsetY, offsetZ, x, x + 1); |
|---|
| 264 | x += 1; |
|---|
| 265 | } |
|---|
| 266 | |
|---|
| 267 | __m128d same0 = _mm_load_pd(src + x + 0); |
|---|
| 268 | __m128d neig0 = _mm_loadu_pd(src + x + 1); |
|---|
| 269 | |
|---|
| 270 | int paddedEndX = endX - 7; |
|---|
| 271 | for (; x < paddedEndX; x += 8) { |
|---|
| 272 | __m128d same1 = _mm_load_pd(src + x + 2); |
|---|
| 273 | __m128d same2 = _mm_load_pd(src + x + 4); |
|---|
| 274 | __m128d same3 = _mm_load_pd(src + x + 6); |
|---|
| 275 | __m128d same4 = _mm_load_pd(src + x + 8); |
|---|
| 276 | |
|---|
| 277 | __m128d neig1 = _mm_shuffle_pd(same0, same1, (1 << 0) | (0 << 2)); |
|---|
| 278 | __m128d neig2 = _mm_shuffle_pd(same1, same2, (1 << 0) | (0 << 2)); |
|---|
| 279 | __m128d neig3 = _mm_shuffle_pd(same2, same3, (1 << 0) | (0 << 2)); |
|---|
| 280 | __m128d neig4 = _mm_shuffle_pd(same3, same4, (1 << 0) | (0 << 2)); |
|---|
| 281 | |
|---|
| 282 | same0 = _mm_mul_pd(same0, _mm_load_pd(&coeff[3][x + 0])); |
|---|
| 283 | same1 = _mm_mul_pd(same1, _mm_load_pd(&coeff[3][x + 2])); |
|---|
| 284 | same2 = _mm_mul_pd(same2, _mm_load_pd(&coeff[3][x + 4])); |
|---|
| 285 | same3 = _mm_mul_pd(same3, _mm_load_pd(&coeff[3][x + 6])); |
|---|
| 286 | |
|---|
| 287 | __m128d temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[2][x + 0])); |
|---|
| 288 | __m128d temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[2][x + 2])); |
|---|
| 289 | __m128d temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[2][x + 4])); |
|---|
| 290 | __m128d temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[2][x + 6])); |
|---|
| 291 | |
|---|
| 292 | same0 = _mm_add_pd(same0, temp1); |
|---|
| 293 | same1 = _mm_add_pd(same1, temp2); |
|---|
| 294 | same2 = _mm_add_pd(same2, temp3); |
|---|
| 295 | same3 = _mm_add_pd(same3, temp4); |
|---|
| 296 | |
|---|
| 297 | temp1 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[4][x + 0])); |
|---|
| 298 | temp2 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[4][x + 2])); |
|---|
| 299 | temp3 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[4][x + 4])); |
|---|
| 300 | temp4 = _mm_mul_pd(neig4, _mm_load_pd(&coeff[4][x + 6])); |
|---|
| 301 | |
|---|
| 302 | same0 = _mm_add_pd(same0, temp1); |
|---|
| 303 | same1 = _mm_add_pd(same1, temp2); |
|---|
| 304 | same2 = _mm_add_pd(same2, temp3); |
|---|
| 305 | same3 = _mm_add_pd(same3, temp4); |
|---|
| 306 | |
|---|
| 307 | neig0 = _mm_load_pd(src + x - offsetZ + 0); |
|---|
| 308 | neig1 = _mm_load_pd(src + x - offsetZ + 2); |
|---|
| 309 | neig2 = _mm_load_pd(src + x - offsetZ + 4); |
|---|
| 310 | neig3 = _mm_load_pd(src + x - offsetZ + 6); |
|---|
| 311 | |
|---|
| 312 | temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[0][x + 0])); |
|---|
| 313 | temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[0][x + 2])); |
|---|
| 314 | temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[0][x + 4])); |
|---|
| 315 | temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[0][x + 6])); |
|---|
| 316 | |
|---|
| 317 | same0 = _mm_add_pd(same0, temp1); |
|---|
| 318 | same1 = _mm_add_pd(same1, temp2); |
|---|
| 319 | same2 = _mm_add_pd(same2, temp3); |
|---|
| 320 | same3 = _mm_add_pd(same3, temp4); |
|---|
| 321 | |
|---|
| 322 | neig0 = _mm_load_pd(src + x - offsetY + 0); |
|---|
| 323 | neig1 = _mm_load_pd(src + x - offsetY + 2); |
|---|
| 324 | neig2 = _mm_load_pd(src + x - offsetY + 4); |
|---|
| 325 | neig3 = _mm_load_pd(src + x - offsetY + 6); |
|---|
| 326 | |
|---|
| 327 | temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[1][x + 0])); |
|---|
| 328 | temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[1][x + 2])); |
|---|
| 329 | temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[1][x + 4])); |
|---|
| 330 | temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[1][x + 6])); |
|---|
| 331 | |
|---|
| 332 | same0 = _mm_add_pd(same0, temp1); |
|---|
| 333 | same1 = _mm_add_pd(same1, temp2); |
|---|
| 334 | same2 = _mm_add_pd(same2, temp3); |
|---|
| 335 | same3 = _mm_add_pd(same3, temp4); |
|---|
| 336 | |
|---|
| 337 | neig0 = _mm_load_pd(src + x + offsetY + 0); |
|---|
| 338 | neig1 = _mm_load_pd(src + x + offsetY + 2); |
|---|
| 339 | neig2 = _mm_load_pd(src + x + offsetY + 4); |
|---|
| 340 | neig3 = _mm_load_pd(src + x + offsetY + 6); |
|---|
| 341 | |
|---|
| 342 | temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[5][x + 0])); |
|---|
| 343 | temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[5][x + 2])); |
|---|
| 344 | temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[5][x + 4])); |
|---|
| 345 | temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[5][x + 6])); |
|---|
| 346 | |
|---|
| 347 | same0 = _mm_add_pd(same0, temp1); |
|---|
| 348 | same1 = _mm_add_pd(same1, temp2); |
|---|
| 349 | same2 = _mm_add_pd(same2, temp3); |
|---|
| 350 | same3 = _mm_add_pd(same3, temp4); |
|---|
| 351 | |
|---|
| 352 | neig0 = _mm_load_pd(src + x + offsetZ + 0); |
|---|
| 353 | neig1 = _mm_load_pd(src + x + offsetZ + 2); |
|---|
| 354 | neig2 = _mm_load_pd(src + x + offsetZ + 4); |
|---|
| 355 | neig3 = _mm_load_pd(src + x + offsetZ + 6); |
|---|
| 356 | |
|---|
| 357 | temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[5][x + 0])); |
|---|
| 358 | temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[5][x + 2])); |
|---|
| 359 | temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[5][x + 4])); |
|---|
| 360 | temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[5][x + 6])); |
|---|
| 361 | |
|---|
| 362 | same0 = _mm_add_pd(same0, temp1); |
|---|
| 363 | same1 = _mm_add_pd(same1, temp2); |
|---|
| 364 | same2 = _mm_add_pd(same2, temp3); |
|---|
| 365 | same3 = _mm_add_pd(same3, temp4); |
|---|
| 366 | |
|---|
| 367 | _mm_store_pd(dst + 0, same0); |
|---|
| 368 | _mm_store_pd(dst + 2, same1); |
|---|
| 369 | _mm_store_pd(dst + 4, same2); |
|---|
| 370 | _mm_store_pd(dst + 6, same3); |
|---|
| 371 | |
|---|
| 372 | same0 = same4; |
|---|
| 373 | neig0 = neig4; |
|---|
| 374 | |
|---|
| 375 | // dst[x] = |
|---|
| 376 | // coeff[0][x] * src[x - offsetZ] + |
|---|
| 377 | // coeff[1][x] * src[x - offsetY] + |
|---|
| 378 | // coeff[2][x] * src[x - 1] + |
|---|
| 379 | // coeff[3][x] * src[x] + |
|---|
| 380 | // coeff[4][x] * src[x + 1] + |
|---|
| 381 | // coeff[5][x] * src[x + offsetY] + |
|---|
| 382 | // coeff[6][x] * src[x + offsetZ]; |
|---|
| 383 | } |
|---|
| 384 | |
|---|
| 385 | scalarUpdater.step(coeff, src, dst, offsetY, offsetZ, x, endX); |
|---|
| 386 | } |
|---|
| 387 | |
|---|
| 388 | int flops() |
|---|
| 389 | { |
|---|
| 390 | return 13; |
|---|
| 391 | } |
|---|
| 392 | }; |
|---|
| 393 | |
|---|
| 394 | |
|---|
| 395 | int main(int argc, char *argv[]) |
|---|
| 396 | { |
|---|
| 397 | // Benchmark<Scalar3D, 3>().exercise(); |
|---|
| 398 | Benchmark<Vectorized3D, 3>().exercise(); |
|---|
| 399 | // Benchmark<VectorizedSSEMelbourneShuffle2D>().exercise(); |
|---|
| 400 | |
|---|
| 401 | |
|---|
| 402 | // std::vector<cl::Platform> platforms; |
|---|
| 403 | // cl::Platform::get(&platforms); |
|---|
| 404 | |
|---|
| 405 | // for (int i = 0; i < platforms.size(); ++i) { |
|---|
| 406 | // std::string str; |
|---|
| 407 | // platforms[i].getInfo(CL_PLATFORM_NAME, &str); |
|---|
| 408 | // std::cout << "Platform[" << i << "] = " << str << std::endl; |
|---|
| 409 | // } |
|---|
| 410 | |
|---|
| 411 | return 0; |
|---|
| 412 | } |
|---|