【问题标题】:Reading and storing large matrix file for GPU为 GPU 读取和存储大型矩阵文件
【发布时间】:2018-08-12 06:35:52
【问题描述】:

目标:在内存中存储一​​个大型矩阵(Radon 矩阵),并将其传输到 GPU 内存中以进行大规模并行操作。

问题:可怕的阅读时间,以及空间的潜在次优使用(但不限制程序的使用)

我可以在 C 或 C++ 中执行此操作。

我收到的文件解析如下:

0.70316,0.71267,0.72221,0.73177,0.74135,0.75094,0.76053,0.77011,0.77967,0.7892,0.79868,0.80811,0.81747

这至少持续 50MB。

我的幼稚实现:

float ** Radon;
Radon = (float **)malloc(HeightxNproj * sizeof(float *));

for (int i = 0; i < Hauteur * Nproj; i++)
    Radon[i] = (float *)malloc(WidthSquared * sizeof(float));

FILE *radonFile;

radonFile = fopen("radon.txt", "r");

if (radonFile == NULL)
{
    printf("Radon file opening failed.");
    return -1;
}

for (int i = 0; i < HeightxNproj; i++) 
{
    for (int j = 0; j < WidthSquared; j++)
    {
        fscanf(radonFile, "%f,", &Radon[i][j]);
    }
}

fclose(radonFile);
printf("Radon loaded.");

我正在为 Windows 编程。我读过一些关于文件内存映射的内容,但我不知道这种实际上并未将矩阵存储在内存中的方法是否与 GPGPU 编程兼容。我正在使用 CUDA,我必须将此矩阵传递到 GPU 内存以进行并行操作。

这种文件读取方法执行得非常糟糕,读取和解析 50MB 文件大约需要一分钟。有没有办法缩短阅读和解析时间?矩阵也是稀疏矩阵,有没有常用的处理方法?

【问题讨论】:

  • 从文本中解析浮点值的性能很糟糕,尤其是fscanf:如果您必须非常精确(特别是如果您除了目标的精度之外还有其他输入,那么这是一个令人惊讶的复杂问题) FP型);此外,fscanf 必须处理额外的约束(语言环境、锁定、...),并且您要为每个单个值支付 fscanf 开销(例如解析格式字符串)。您应该通过将文件映射到内存中直接解析二进制数据(或者如果文件不是太大,则直接在内存中读取),或者使用更有效的解析策略。
  • 感谢您的澄清,至少我了解更多幕后发生的事情以及为什么如此缓慢。选定答案的方法给了我一个非常快的阅读时间。谢谢!

标签: c++ c matrix gpu sparse-matrix


【解决方案1】:

文件的单独访问越多,您损失的性能就越多。您应该采取的第一步是估计需要从文件中读取的信息数量并一次性读取。它将大大提高你的表现。您可以使用内存映射文件。

这至少持续 50MB。

这还不算多。

我收到的文件解析如下: 0.70316,0.71267,0.72221,0.73177,0.74135,0.75094,0.76053,0.77011,0.77967,0.7892,0.79868,0.80811,0.81747

  • 以二进制形式保存它可以节省大约一半的内存(甚至更多)。这也将提高阅读速度。
  • 一次读取整个文件。

一个例子会让你意识到你的方法是多么幼稚和缓慢:

有一次我正在实现读取.obj 3d 模型的算法。该模型大约为 10 MB,加载大约需要 1-2 分钟。这很奇怪,因为 Blender 可以立即加载它——可能需要 1 或 2 秒。将整个文件映射到内存并预先分配缓冲区使我能够在不到 5 秒的时间内加载文件。

注意:

我可以在 C 或 C++ 中执行此操作,都可以。

在内存管理方面,切勿将 C 与 C++ 混为一谈,除非您确定自己在做什么。如果您不使用 RAII 保护 C 动态分配的内存,C++ 异常可能会导致大量内存泄漏。

【讨论】:

  • 感谢您的回复。我无法控制传入的文件,但我会与提供文件的人讨论。对于内存映射文件,我可以将数据传输到 GPU 吗?没有 GPU 内存映射文件将是解决方案,但是对于 cpu 和 gpu 使用不同的内存存储,我不知道这是否可行。 (编辑后)我会尝试一次读取文件,将整个文件放在一个字符串/字符**中并在此之后进行解析会导致这样的时间增益吗?还是真的是二值化可以节省这么多?
  • 两者:二值化和读取整个文件会给你带来巨大的提升。您无需更改传入文件。创建缓存文件,该文件将被“二进制化”一次,然后每次访问保存在该文件中的数据都会快得多。内存映射文件不应该对 GPU 产生任何影响:它只是访问文件数据的一种方式。
  • 使用此方法生成的文件是原始文件大小的两倍+,但读取时间从整整一分钟缩短到半秒以下。非常感谢!
  • 大小可能会翻倍,因为我认为您显示的大多数数字都使用 7 个 ASCII 字符 + 一个逗号作为分隔符,即 8 个字节。转换为浮点数在大多数情况下每个需要 4 个字节,因此大小只有一半。恭喜你让算法更快:)
  • 谢谢,它翻了一番,因为 60% 的文件是 0,由于矩阵稀疏,现在这些 0 确实存储在 4 个字节中
猜你喜欢
  • 2013-04-09
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2012-08-14
  • 1970-01-01
  • 2019-11-04
  • 2018-11-21
  • 2016-12-26
相关资源
最近更新 更多