#sycl
Вопрос:
Привет, я так новичок в c и sycl. Поэтому, пожалуйста, будьте как можно более конкретны. Вот код, который я пытаюсь скомпилировать:
/*
Intel oneAPI DPC
dpcpp -Qstd=c 17 /EHsc hellocl.cpp -Qtbb opencl.lib -o d.exe
Microsoft C Compiler
cl /EHsc /std:c 17 hellocl.cpp opencl.lib /Fe: m.exe
clang -std=c 17 hellocl.cpp -ltbb -lopencl -o c.exe
g -std=c 17 hellocl.cpp -ltbb -lopencl -o c.exe
*/
/*
1. How to use Random Number Generator
2. How to use std::vector as 2-dimensional array
3. How to suppress warning in clang compiler
4. How to use Tpf_FormatWidth, Tpf_FormatPrecision macros
dpcpp naive.cpp tbbmalloc.lib -o d.exe
*/
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpass-failed"
#endif
#define Tpf_FormatWidth 6
#define Tpf_FormatPrecision 4
#include "tpf_linear_algebra.hpp"
#include <cl/sycl.hpp>
namespace chr = tpf::chrono_random;
namespace mtx = tpf::matrix;
tpf::sstream stream;
autoamp; nl = tpf::nl; // single carriage-return
autoamp; nL = tpf::nL; // two carriage-return
autoamp; endl = tpf::endl; // sing carriage-return and flush out to console
autoamp; endL = tpf::endL; // two carriage-returns and flush out to console
void test_random_number_generator()
{
using element_t = double;
using matrix_t = mtx::scalable_fast_matrix_t<element_t>;
size_t N = 10; // number of rows
size_t M = N; // number of columns
matrix_t A{ N, M }; // N x M matrix
matrix_t B{ N, M };
// we created a random number generator
// <int> means we generator integer
// (-10, 10) means from -10 to 10, inclusive
auto generator = chr::random_generator<int>(-10, 10);
chr::random_parallel_fill(A.array(), generator);
chr::random_parallel_fill(B.array(), generator);
auto C = A * B; // matrix multiplication
stream << "A = " << nl << A << endl;
stream << "B = " << nl << B << endl;
stream << "A x B = " << nl << C << endL;
}
void test_naive_matrix_multiplication()
{
size_t N = 10;
size_t M = N;
using element_t = double;
using vectrix_t = std::vector<element_t>;
vectrix_t A(N * M);
vectrix_t B(N * M);
vectrix_t C(N * M);
vectrix_t D(N * M);
auto generator = chr::random_generator<int>(-10, 10);
chr::random_parallel_fill(A, generator);
chr::random_parallel_fill(B, generator);
auto out_A = mtx::create_formatter(A, N, M);
auto out_B = mtx::create_formatter(B, N, M);
auto out_C = mtx::create_formatter(C, N, M);
auto out_D = mtx::create_formatter(D, N, M);
stream << "A = " << nl << out_A() << endl;
stream << "B = " << nl << out_B() << endl;
auto idx_A = mtx::create_indexer(A, N, M);
auto idx_B = mtx::create_indexer(B, N, M);
auto idx_C = mtx::create_indexer(C, N, M);
for (int i = 0; i < (int)N; i)
{
for (int j = 0; j < (int)M; j)
{
for (int k = 0; k < (int)M; k)
idx_C(i, j) = idx_A(i, k) * idx_B(k, j); // matrix multiplication
}
}
stream << "CPU: A x B = " << nl << out_C() << endl;
sycl::queue queue{ sycl::gpu_selector{} };
sycl::buffer buf_A{ amp;A[0], sycl::range{N, M} };
sycl::buffer buf_B{ amp;B[0], sycl::range{N, M} };
sycl::buffer buf_D{ amp;D[0], sycl::range{N, M} };
queue.submit([amp;](sycl::handleramp; cgh)
{
auto a = buf_A.get_access<sycl::access::mode::read>(cgh);
auto b = buf_B.get_access<sycl::access::mode::read>(cgh);
auto d = buf_D.get_access<sycl::access::mode::read_write>(cgh);
constexpr int tile_size = 16;
local_accessor<int> tileA{tile_size, cgh};
cgh.parallel_for(
nd_range<2>{{N, N}, {1, tile_size}}, [=](nd_item<2> it) {
// Indices in the global index space:
int m = it.get_global_id()[0];
int n = it.get_global_id()[1];
// Index in the local index space:
int i = it.get_local_id()[1];
size_t sum = 0;
for (int kk = 0; kk < 496; kk = tile_size) {
// Load the matrix tile from matrix A, and synchronize
// to ensure all work-items have a consistent view
// of the matrix tile in local memory.
tileA[i] = a[m][kk i];
it.barrier();
// Perform computation using the local memory tile, and
// matrix B in global memory.
for (int k = 0; k < tile_size; k )
sum = tileA[k] * b[kk k][n];
// After computation, synchronize again, to ensure all
// reads from the local memory tile are complete.
it.barrier();
}
// Write the final result to global memory.
d[m][n] = sum;
});
});
// when this block goes off,
// the destructor of buf_D waits until it is released by the queue
// and copies to its host memory D
stream << "GPU: A x B = " << nl << out_D() << endl;
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
int main()
{
// test_random_number_generator();
test_naive_matrix_multiplication();
}
Это простой код умножения матриц, и я пытаюсь использовать ND_kernel для этого приложения sycl. Но я получаю подобные ошибки, когда пытаюсь его скомпилировать:
hellocl.cpp(128,13): ошибка: нет шаблона с именем «local_accessor» local_accessor tileA{размер tile_size, cgh}; ^ hellocl.cpp(131,1): ошибка: использование необъявленного идентификатора ‘nd_range’ nd_range<2>{{N, N}, {1, tile_size}}, [=](nd_item<2><2> it) { ^ 2 сгенерированных ошибок.
Пример ND_range взят из книги «Параллельный анализ данных C » из https://www.khronos.org/developers/books/. со страницы 225.
Ответ №1:
Классы, упомянутые в журнале ошибок ( local_accessor
, nd_range
, nd_item
), являются частью SYCL и как таковые содержатся в sycl::
пространстве имен. Вам нужно добавить префикс к этим типам sycl::
, аналогично тому, как вы делаете это с вашими буферами и очередью. Так что пишите sycl::local_accessor
вместо того, чтобы просто local_accessor
.
Комментарии:
1. После того, как я опубликовал этот выпуск, я сделал именно то, что вы сказали. Но на этот раз, когда я попытался скомпилировать, я получил ошибку как ; ошибка: нет шаблона с именем «local_accessor» в пространстве имен «sycl»; вы имели в виду «host_accessor»? sycl::local_accessor<int> tileA{размер tile_size, cgh}; ~~~~~~^~~~~~~~~~~~~~ host_accessor
2. local_accessor-это новый тип, который был представлен в SYCL 2020 и, следовательно, все еще является довольно новым. Я бы посоветовал проверить вашу реализацию SYCL, поддерживает ли она ее уже, и убедиться, что вы используете последнюю версию. Какую реализацию SYCL вы используете?
3. Спасибо вам за вашу помощь. В настоящее время я использую библиотеки intel oneapi. Я добавил переменную окружения, чтобы получить ее из VS-кода. Я не знаю точно, как это проверить. А также как я могу проверить, поддерживает ли это моя реализация sycl?