我是 oneAPI 和类似框架的新手,所以我在使用 SYCL 数据缓冲区进行数据管理时遇到了麻烦。
我的任务是使用 Aho-Corasick 算法在给定字符串中查找子字符串。
我的想法是构建一个 trie,然后提交一个内核,该内核将在 trie 中并行查找子字符串。因此,为此我创建了一个 SYCL 队列,为字符串(用于在其中查找子字符串)、向量(用于存储搜索结果)和我的 Aho-Corasick 对象创建了缓冲区,该对象包含先前构建的树的根. 但是,关于最后一个我不确定,因为我正在为主机内存中的一个对象创建一个缓冲区,该缓冲区包含指向其他对象的指针(例如节点,它包含指向其他节点的指针)。
Node对象的结构:
class Node {
typedef Node *node_ptr;
private:
std::set<std::pair<int, std::string>> retVals;
std::unordered_map<char, node_ptr> children;
node_ptr fail;
char value;
这是搜索方法:
void
matchWords(char *text, int startIdx, int endIdx, cl::sycl::cl_int *matched) {
node_ptr child = start;
int item = startIdx;
for (int i = startIdx; i < endIdx; ++i) {
child = child->nextNode(text[i]);
if (child == nullptr) {
child = start;
continue;
}
for (const auto &returns: child->getRetVals()) {
matched[item++] = returns.first;
if (item == endIdx) item = startIdx;
}
}
}
缓冲器:
cl::sycl::buffer<char, 1> fasta_buf(tempFasta.data(), cl::sycl::range<1>(len));
cl::sycl::buffer<cl::sycl::cl_int, 1> vec_buf(vec.data(), cl::sycl::range<1>(len));
cl::sycl::buffer<aho_corasick::AhoCorasick, 1> aho_buf(a, cl::sycl::range<1>(1));
并排队求和:
q.submit([&](cl::sycl::handler &cgh) {
auto string_acc = fasta_buf.get_access<cl::sycl::access::mode::read>(cgh);
auto vec_acc = vec_buf.get_access<cl::sycl::access::mode::read_write>(cgh);
auto aho_acc = aho_buf.get_access<cl::sycl::access::mode::read>(cgh);
cgh.parallel_for<class dummy>(
cl::sycl::range<1>(10), [=](cl::sycl::item<1> i) {
// 10 is the number of workers I want
int startInx = (int) (i.get_linear_id() * (len / 10));
int endInx = (int) ((i.get_linear_id() + 1) * (len / 10));
aho_acc.get_pointer()->matchWords(string_acc.get_pointer(), startInx, endInx, vec_acc.get_pointer());
});
});
q.wait_and_throw();
我发现程序在尝试访问子地图的项目后失败了。因此,我认为问题在于存储在 map 中的指针是指向主机内存的指针,设备无权访问。