1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
//==============================================================
// Copyright Intel Corporation
//
// SPDX-License-Identifier: MIT
// =============================================================
#include <iostream>
#include <vector>
#include <string>
#include <type_traits>
#include <CL/sycl.hpp>
#include <sycl/ext/intel/fpga_extensions.hpp>
// dpc_common.hpp can be found in the dev-utilities include folder.
// e.g., $ONEAPI_ROOT/dev-utilities//include/dpc_common.hpp
#include "dpc_common.hpp"
// This code sample demonstrates how to split the host and FPGA kernel code into
// separate compilation units so that they can be separately recompiled.
// Consult the README for a detailed discussion.
// - host.cpp (this file) contains exclusively code that executes on the host.
// - kernel.cpp contains almost exclusively code that executes on the device.
// - kernel.hpp contains only the forward declaration of a function containing
// the device code.
#include "kernel.hpp"
using namespace sycl;
template <typename K>
void printMatrix(std::vector<K> &vec, int col, std::string msg) {
std::cout << msg << ":" << std::endl << "[" << std::endl;
for (size_t i=0; i<vec.size(); ++i) {
std::cout << vec.at(i);
if (i<vec.size()-1 && vec.size() > 1) {
std::cout << ",\t";
}
if (i%col == col-1) {
std::cout << std::endl;
}
}
std::cout << "]" << std::endl;
}
template <typename K>
void printVec(std::vector<K> &vec, std::string msg) {
std::cout << msg << ": ";
std::cout << "[";
for (size_t i=0; i<vec.size(); ++i) {
std::cout << vec.at(i);
if (i<vec.size()-1 && vec.size() > 1) {
std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
int main() {
std::vector<float> a = { 2, 1, 1, 1, 0, 0,
1, 3, 2, 0, 1, 0,
2, 1, 2, 0, 0, 1};
std::vector<float> c = {-6, -5, -4, 0, 0, 0};
std::vector<float> b = {180, 300, 240};
std::vector<int> resultFlags = {-1, -1, -1};
// Select either the FPGA emulator or FPGA device
#if defined(FPGA_EMULATOR)
ext::intel::fpga_emulator_selector device_selector;
#else
ext::intel::fpga_selector device_selector;
#endif
try {
// Create a queue bound to the chosen device.
// If the device is unavailable, a SYCL runtime exception is thrown.
queue q(device_selector, dpc_common::exception_handler);
// make sure the device supports USM device allocations
device d = q.get_device();
if (!d.get_info<info::device::usm_device_allocations>()) {
std::cerr << "ERROR: The selected device does not support USM device"
<< " allocations\n";
return 1;
}
printMatrix(a, 6, "a");
printVec(resultFlags, "result flags");
// The definition of this function is in a different compilation unit,
// so host and device code can be separately compiled.
double timePassed = RunKernel(q, a, b, c, resultFlags);
std::cout << "------------------------" << std::endl;
printMatrix(a, 6, "a");
printVec(resultFlags, "result flags");
std::cout << std::endl << std::endl;
std::cout << "timePassed: " << timePassed << std::endl;
} catch (exception const &e) {
// Catches exceptions in the host code
std::cerr << "Caught a SYCL host exception:\n" << e.what() << "\n";
// Most likely the runtime couldn't find FPGA hardware!
if (e.code().value() == CL_DEVICE_NOT_FOUND) {
std::cerr << "If you are targeting an FPGA, please ensure that your "
"system has a correctly configured FPGA board.\n";
std::cerr << "Run sys_check in the oneAPI root directory to verify.\n";
std::cerr << "If you are targeting the FPGA emulator, compile with "
"-DFPGA_EMULATOR.\n";
}
std::terminate();
}
std::cout << "done\n";
return 0;
}
|