【问题标题】:Efficient Way to Read/Write Vectors to File将向量读/写到文件的有效方法
【发布时间】:2016-02-29 23:19:17
【问题描述】:

概述:经过几天的研究,我一直无法找到一种快速、有效的方法来向文件写入/读取向量。我看到的大多数答案都涉及将每个单独的元素推入/弹出文件。随着元素数量的增加,这非常耗时。此外,我一直无法尝试解决我的特定问题。因此,请确保您的解决方案适用于我的特定情况(即阅读整个问题)。

我的问题:我有一个非常大的数据结构,其中包含有关图像的像素信息。有 60,000 张图像,每张 784 像素。每张图片都是手写数字的图像。因此,除了 60,000 * 784 像素之外,我还需要包含一个标签,以便我知道图像代表哪个数字。我使用的标签,从整个项目的范围来看是必要的,是一个包含 10 种可能性的向量,代表 0、1、2 ... 9,其中只有一个包含“1”/真”,其余为“0”/“假”。此外,由于项目其余部分的线性代数要求,此数据结构要求将信息存储在犰狳线性代数库中使用的“Col”结构中。因此,我希望保存/读取/读取文件的结构声明为std::vector<std::vector<arma::Col<double>>>

这是我现在用来保存数据的函数,以提供上下文:

void SaveTrainingData(vector<vector<Col<double>>> trainingData) //format: trainingData[60000][2][784, 10]
{
    ofstream ofile("VectorizedTrainingData.dat", ios::binary);

    for (int i = 0; i < trainingData.size(); i++)
        for (int j = 0; j < trainingData[i].size(); j++)
            for (int k = 0; k < trainingData[i][j].size(); k++)
                ofile.write((char *)&trainingData[i][j][k], sizeof(double));
}

如果您有任何问题,请不要犹豫!提前致谢。

【问题讨论】:

  • void SaveTrainingData(vector&lt;vector&lt;Col&lt;double&gt;&gt;&gt; trainingData) 如果您没有按值传递向量,则仅通过函数调用可能会加快速度。此外,您是在启用优化的情况下运行此程序,还是在程序的“调试”未优化版本的情况下运行它?另外,请注意,磁盘 I/O 在某些方面是难以优化的,因为它很大程度上取决于磁盘的性能。

标签: c++ file vector armadillo


【解决方案1】:

我不得不查找有关此 Armadillo 库的文档,但似乎 Col 是一个连续的密集向量类。我们可以依靠连续表示来消除嵌套循环,如下所示:

// format: trainingData[60000][2][784, 10]
void SaveTrainingData(const vector<vector<Col<double>>>& trainingData) 
{
    ofstream ofile("VectorizedTrainingData.dat", ios::binary);

    const int numImages = trainingData.size();
    for (int i = 0; i < numImages; i++)
    {
        const vector<Col<double>>& img = trainingData[i];
        const int numCols = img.size();
        for (int j = 0; j < numCols; j++)
        {
            const Col<double>& col = img[j];
            ofile.write((char*)&col[0], col.size()*sizeof(double));
        }
    }
}

write 的调用频率从一列中的一个元素减少到一整列可能已经有所帮助。

这可能是值得测量的,以确保您实际上更多的是 I/O 绑定而不是内存绑定。涉及所有这些列向量向量的潜在内存碎片有点棘手。

例如,如果内部向量的大小始终相同(每张图像都是 784 像素的情况似乎就是这种情况),您可能会使用连续的vector&lt;Col&gt; 获得更好的结果,或者这个:

struct Image
{
     Col pixels[768];
};
...
vector<Image> trainingData;

... 或类似的东西。 .我不能完全理解线性代数如何与图像表示相关联,但希望这能提供一个想法。

【讨论】:

  • 非常感谢!这肯定会对我有很大帮助。线性代数的东西稍后会与项目的其余部分联系起来,所以在这里并不真正相关,只是对程序的其余部分是必需的。
  • 您在读取文件时有什么额外的输入吗?
  • @Rob 阅读应该与写作相当对称——你几乎可以做同样的事情。不要认为我们可以在那里做任何额外的事情——几乎是二进制数据的直接 I/O。
【解决方案2】:

我没有使用过犰狳,但由于 Col 是一个 1xN 矩阵并且应该以线性方式存储,因此您可以摆脱 k 循环并一次性写出整个列:

ofile.write((char *)&trainingData[i][j][0], sizeof(double) * trainingData[i][j].size());

如果这不起作用,请将元素从 Col 复制到本地向量,然后将它们写出到文件中(因为文件操作会比复制一些双精度值慢得多)。

您可能还想在写入所有元素之前写出矢量的大小,以便知道要读入的元素数量。

【讨论】:

  • 谢谢!我会试试看!另外,我通常在元素之前将向量的大小写入文件,但这一次,为了尽可能多地消除不必要的数据(因为我提前知道所有向量的大小),我将其删除.
猜你喜欢
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多