检查内存是否归零的最快方法

时间:2009-06-01 04:43:42

标签: c++ windows linux

我有一个程序需要检查文件的块是否归零或是否有数据。这个alg运行整个文件的大小达到几个演出并需要一段时间才能运行。有没有更好的方法来检查它是否归零?

平台:Linux和Windows

bool WGTController::isBlockCompleted(wgBlock* block)
{
    if (!block)
        return false;

    uint32 bufSize = (uint32)block->size;
    uint64 fileSize = UTIL::FS::UTIL_getFileSize(m_szFile);

    if (fileSize < (block->size + block->fileOffset))
        return false;

    char* buffer = new char[bufSize];

    FHANDLE fh=NULL;

    try
    {
        fh = UTIL::FS::UTIL_openFile(m_szFile, UTIL::FS::FILE_READ);
        UTIL::FS::UTIL_seekFile(fh, block->fileOffset);
        UTIL::FS::UTIL_readFile(fh, buffer, bufSize);
        UTIL::FS::UTIL_closeFile(fh);
    }
    catch (gcException &)
    {
        SAFE_DELETEA(buffer);
        UTIL::FS::UTIL_closeFile(fh);
        return false;
    }

    bool res = false;

    for (uint32 x=0; x<bufSize; x++)
    {
        if (buffer[x] != 0)
        {
            res = true;
            break;
        }
    }

    SAFE_DELETEA(buffer);
    return res;
}

7 个答案:

答案 0 :(得分:6)

'一段时间'有多长? ...我想尝试比较尽可能多的并行值会有所帮助,也许可以使用一些SIMD指令一次比较超过4个字节?

请注意,无论您进行比较的速度有多快,最终仍需要从文件中读取数据。如果文件尚未位于内存中的某个高速缓存中,则在磁盘带宽饱和之前,最大可能限制为100-150 MB / s。如果你已经达到了这一点,那么你可能首先需要看一个避免必须加载文件的方法,或者只是接受它不会比这更快的事实。

答案 1 :(得分:2)

文件/块中是否存在更可能具有非零值的位置?您只需找到一个非零值(您的中断条件),因此请先查看最有可能找到它们的位置 - 这不一定是文件/块的开头。根据实际应用,从最后开始或检查中间的1/3可能是有意义的。

但是,我不建议随机跳到不同的位置;从磁盘读取可能会变得令人难以置信;)..

答案 2 :(得分:0)

我想查看此功能的汇编输出。 你可以做的事情会加速很多,就是使用SSE指令。使用这些指令,您可以一次加载8个字节,将它们全部检查为零并继续。 你也可以将它循环展开几次。

答案 3 :(得分:0)

你的算法似乎没问题,但如果事先知道你会得到什么类型的文件,你可以尝试优化起始位置......但如果它是一个特定的文件,那么很可能信息将在标题中(前几个字节)。

同时确保调用方法的人阻止&gt;大小不是1:)

同时查看Boost的内存映射文件工具......这可能会有所帮助,具体取决于您如何计算最佳块 - &gt; size

答案 4 :(得分:0)

我有一个“开箱即用”的答案,但我不确定在你的情况下实施是否可行。

如果你不控制转储过程:因为它是一个在excpetional情况下产生的大型恢复(转储?)文件,为什么不在它被转储后立即扫描低优先级的文件(0字节)然后标记它以某种方式以后更快识别? (或者你可以压缩它并稍后解析/扫描zip文件)

或者如果你控制转储过程:(你必须要做的一个缓慢的过程)为什么不在转储文件的末尾指示(或者在转发文件的开头写回),如果转储文件被填满0或有一些有效数据(因为你写了它,你知道它是什么)?就像你不必两次支付I / O费用一样。

这里的目标是通过将procss设置为另一个更好的时间来使读取更快,因为当转储发生时,不太可能有操作员等待它加载。

答案 5 :(得分:0)

首先,每次都不要分配新的缓冲区。分配一个(每个线程)并重用它。使用一个漂亮的大块,并做多个阅读/检查通行证 其次,不要比较每个角色。对较大的积分类型进行比较。很可能你会想要一个32位的int,但是根据你的os /编译器,使用64位甚至128位int可能会更快。使用32位int,您可以将比较次数减少4倍。当然,您的意愿必须担心最终条件。为此,很容易,如果您要比较的缓冲区不是int大小的偶数倍,只需在执行比较之前将最后X个字节设置为0。 第三,它可能有助于你的编译器展开循环。在循环体中进行4或8次比较。这应该有助于编译器优化一点,并减少退出循环的比较次数。确保缓冲区是比较类型的倍数x循环中的比较数。 第四,使用(* pBuffer ++)代替buffer [i]可能更快,特别是如果缓冲区很大的话。

对于其中任何一种,您当然希望获得一些指标,看看实际有什么帮助。

答案 6 :(得分:0)

我会告诉你一个肮脏,不便携和困难的方式,但可以更有效...如果你正在处理稀疏文件,你真的很无聊,想要弄乱文件系统的内部你'重新使用,你可以尝试添加一个新的函数,返回一个位图,指示哪些块被映射,哪些不是(未映射的那些被归零,其余的你仍然需要手动检查)。

是的,我知道这很疯狂,没有人愿意做像这样的事情xD