В моем коде у меня есть динамическая матрица.
int ** file_data = (int **)malloc(TRANSACTIONS * sizeof(int *));
file_data[0] = (int *)malloc((a_size+1) * sizeof(int));
file_data[1] = (int *)malloc((a_size+1) * sizeof(int));
file_data[2] = (int *)malloc((a_size+1) * sizeof(int));
................................................................
Я хочу скопировать его в глобальную память устройства только один раз.
Я использовал:
__device__ int raw_data[][];
...................................
...................................
...................................
cudaMemcpyToSymbol(raw_data[i], file_data[i], (a_size+1)*sizeof(int));
Но это не работает.
Как мне это сделать?
Если у вас есть несколько операторов malloc
в вашем коде хоста, как показано здесь, отдельно для каждой строки, существует нет безопасного пути для копирования этих данных на устройство с использованием только одной операции cudaMemcpy
или cudaMemcpyToSymbol
. Это невозможно сделать. Если вы хотите использовать единственную операцию копирования, вам нужно будет внести некоторые изменения. здесь охватывает большое количество методов.
@ Ptaq666 выдает «Ошибка CUDA: недопустимый символ устройства».
Если вы в первую очередь работаете только с прямоугольными матрицами, я бы рекомендовал всегда хранить ваши матрицы в таком виде, но в любом случае вам нужно будет привести их в эту форму, прежде чем пытаться отправить эти данные в память вашего устройства. .
template<typename T>
class Matrix {
std::vector<T> _data;
size_t rows, columns;
public:
Matrix(size_t rows, size_t columns) :rows(rows), columns(columns) {
_data.resize(rows * columns);
}
T & operator()(size_t row, size_t column) & {
return _data.at(row * columns + column); //Row-Major Ordering
}
T const& operator()(size_t row, size_t column) const& {
return _data.at(row * columns + column);
}
T operator() size_t row, size_t column) const {
return _data.at(row * columns + column);
}
T * data() & {
return _data.data();
}
T const* data() const& {
return _data.data();
}
std::pair<size_t, size_t> size() const {
return {rows, columns};
}
size_t flat_size() const {
return rows * columns;
}
size_t byte_size() const {
return flat_size() * sizeof(T);
}
};
int ** file_data = (int **)malloc(TRANSACTIONS * sizeof(int *));
file_data[0] = (int *)malloc((a_size+1) * sizeof(int));
file_data[1] = (int *)malloc((a_size+1) * sizeof(int));
file_data[2] = (int *)malloc((a_size+1) * sizeof(int));
//................................................................
Matrix<int> flat_data(TRANSACTIONS, a_size + 1);
for(size_t row = 0; row < TRANSACTIONS; row++) {
for(size_t column = 0; column < a_size + 1; column++) {
flat_data(row, column) = file_data[row][column];
}
}
//ALTERNATIVE: use this instead of your manual mallocs in the first place!
cudaMemcpyToSymbol(flat_data.data(), /*buffer name*/, flat_data.byte_size());
Это имеет большое преимущество, заключающееся в том, что вам не нужно копировать каждую строку по отдельности в свои собственные буферы, вы можете собрать их все вместе в памяти, экономя память и уменьшая количество вызовов API, которые вам нужно сделать. И класс, разработанный специально для обработки вашей функциональности, не сломается, когда вы неизбежно совершите ошибку, пытаясь вручную обработать все управление указателями в исходном коде.
@ user10933809 Такое решение почти никогда не рекомендуется. Большинство сред гетерогенных вычислений имеют не особенно высокие ограничения на количество буферов, которые могут быть индивидуально адресованы для одного ядра. Если набор данных OP явно не ограничен очень небольшим числом (т. Е. TRANSACTIONS
меньше 100), такое решение просто нежизнеспособно. Что я сделал, так это предоставил полезную структуру для быстрого преобразования их «массива указателей» на стороне хоста в плоский массив, который будет соответствовать макету данных, ожидаемому буферами данных устройства.
без сомнения, здесь массив должен быть сглажен. Мне просто интересно, не могли бы вы предоставить решение с массивом указателей.
@ user10933809 Как я уже сказал: такое решение нежизнеспособно.
Нет, это не прямоугольная матрица @Xirema.
@Армено Это нормально; решение работает так, как если бы число, которое вы передаете как количество столбцов, равно самой большой строке ваших входных данных.
Спасибо @Xirema, но я ищу другой метод.
@Armeno Ну, если ваше ограничение «Я хочу скопировать его в память устройства только один раз», я не знаю, какое другое решение существует ...
@oblivion нет.ничего нет
А что не так с
cudaMalloc
иcudaMemcpy
?