【问题标题】:How to copy dynamic matrix to device memory in CUDA?如何将动态矩阵复制到 CUDA 中的设备内存?
【发布时间】:2019-10-15 09:39:35
【问题描述】:

在我的代码中,我有动态矩阵。

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));

但这不起作用。

我该怎么做?

【问题讨论】:

  • cudaMalloccudaMemcpy 有什么问题?
  • 如果您的主机代码中有多个 malloc 语句,如此处所示,每行一个单独的语句,则没有安全的方法将该数据复制到该设备仅使用单个cudaMemcpycudaMemcpyToSymbol 操作。这是不可能的。如果要使用单个复制操作,则需要进行一些更改。涵盖了多种技术here
  • @Ptaq666 它给出“CUDA 错误:无效的设备符号”。

标签: c++ matrix cuda global-variables nvidia


【解决方案1】:

你需要扁平化数据

如果您首先只使用矩形矩阵,我建议您始终像这样存储矩阵,但无论哪种方式,您都需要在尝试将此数据推送到此表单之前将其放入此表单您的设备内存。

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。
  • @Armeno 好吧,如果你的约束是“我只想将它复制到设备内存一次”,我不知道还有什么其他解决方案......
猜你喜欢
  • 2017-03-23
  • 2013-04-26
  • 2013-03-25
  • 2013-06-06
  • 1970-01-01
  • 2020-09-11
  • 2014-10-18
  • 2012-11-04
  • 1970-01-01
相关资源
最近更新 更多