我有一个程序需要检查文件的块是否归零或是否有数据。这个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;
}
答案 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