Хабр Курсы для всех
РЕКЛАМА
Большая витрина: от крупнейших школ до частных авторов. Сравнивайте по цене, длительности, формату и выбирайте самый подходящий курс!
В корень проекта добавим папку src в которую поместим файлы с исходным кодом. В папке src создадим четыре файла: main.rs — код основной программы, dot.cpp — С++ binding (обертка для CUDA C), dot_gpu.h, dot_gpu.cu — файл в котором содержится код выполняемый на GPU.
По сути, CUDA используется, как и раньше использовалась. Статей, как использовать, на хабре достаточно.
А почему .cpp, если все равно всё в extern "C"?
Потому-что функция написана на языке C.
What is the effect of extern “C” in C++?
Is extern “C” no longer needed anymore in cuda?
Мой вопрос всё же был не о том, что такое extern "C". Просто C++ тут только ради <iostream> и cout. Можно было и на C всё написать вполне.
Интересно, насколько реально сделать безкостыльное GPGPU с помощью AMDGPU бэкенда LLVM?
вызвать этот кернел из Rust и результат вернуть обратно.
unsafe {
gpu_res = dot(v1.as_mut_ptr(), v2.as_mut_ptr(), VEC_SIZE);
}
dot__<<<blocksPerGrid, threadsPerBlock>>>(dev_v1, dev_v2, dev_res, (int)N);
формально это вызов си-функци
что помимо самого кернела, если вы посмотрите внимательно в файл dot_gpu.cu, есть предшествующий код в виде инициализации памяти на GPU
это все уже относится к СUDA.
Так что вызов си-функции обвязки из раста в которой находится CUDA-зависимый код в том числе вызов самого кернела и которая возвращает результат работы кернела, можно грубо назвать «вызовом кернела из раста».
Нельзя. Это вызов обёртки dot, которая вызывает обёртку, которая вызывает кернел. dot никоим образом не вызвает кернел.
Поэтому как это не называй — это обычный вызов сишной функции из раста. Этот вызов никак не связан с cuda, вообще никак.
Эту обертку поверх обертки можно убрать, не принципиально, тут уже на ваш вкус и зависит от архитектурного решения вашего приложения. В статье приведен лишь пример не более.
Да, это обычный вызов сишной функции в которой мы можем писать CUDA код (а можем и не писать, можем ее вообще не вызывать), спорить не буду, можете называть этот вызов функции как вам удобно)
Это ничего не изменит.
И даже если принять вашу логику — кернелом будет gpu_dot, но вы её не вызываете — вы вызываете обёртку над gpu_dot.
Ну это принципиальный момент. По-сути из статьи можно выкинуть cuda и ничего не изменится, т.к. статья чисто про вызов сишной функции из раста.
Изменит)
Если принять мою логику то gpu_dot будет кернелом а уже эту функцию я могу вызвать из раст) Так что если принять мою логику то это изменит кое что.
Этот туториал в том числе можно использовать как инструкцию для вызова обычного си кода из раст, в комментариях это уже упоминалось, посмотрите выше. В статье рассказывается как писать и собирать Rust + С + CUDA C.
В статье рассказывается как писать и собирать Rust + С + CUDA C.
И в качестве примера напишем небольшую программу на Rust для вычисления скалярного произведения векторов, вычисление скалярного произведения будет производиться на GPU с использованием CUDA C.
Где вы написали на rust программу для «вычисления скалярного произведения векторов»?
extern crate libc;
extern crate rand;
use libc::{c_float, size_t};
use rand::Rng;
const VEC_SIZE: usize = 10;
const MAX: f32 = 10.;
const MIN: f32 = 0.;
extern "C" {
fn dot(v1: *mut c_float, v2: *mut c_float, N: size_t) -> c_float;
}
fn cpu_dot(v1: Vec<f32>, v2: Vec<f32>) -> f32 {
let mut res: f32 = 0.;
for i in 0..v1.len() {
res += v1[i] * v2[i];
}
return res;
}
fn main() {
let mut v1: Vec<f32> = Vec::new();
let mut v2: Vec<f32> = Vec::new();
let mut gpu_res: c_float;
let mut cpu_res: f32 = 0.;
let mut rng = rand::thread_rng();
for _ in 0..VEC_SIZE {
v1.push(rng.gen_range(MIN, MAX));
v2.push(rng.gen_range(MIN, MAX));
}
println!("{:?}", v1);
println!("{:?}", v2);
println!("GPU computing started");
// unsafe {
//gpu_res = dot(v1.as_mut_ptr(), v2.as_mut_ptr(), VEC_SIZE);
// }
println!("GPU computing finished");
println!("GPU dot product result: {}", gpu_res);
cpu_res = cpu_dot(v1, v2);
println!("CPU dot product result: {}", cpu_res);
}Я отвечу — нигде.
Я слушаю про внимательность и тому подобное.
в нем ищем функцию cpu_dot, которая вычисляет скалярное произведение двух векторов на языке Rust
И в качестве примера напишем небольшую программу на Rust для вычисления скалярного произведения векторов, вычисление скалярного произведения будет производиться на GPU
вычисление скалярного произведения будет производиться на GPU
cpu_dot
Пишем на Rust + CUDA C