【问题标题】:Reading file with "gaps" in destination array在目标数组中读取带有“间隙”的文件
【发布时间】:2013-12-05 01:03:21
【问题描述】:

我正在尝试找到一种将文件读入具有“间隙”的数组的方法:
所以读取的数据在字节数组bufferbuffer[0], buffer[2], .., buffer[2*i]的位置,没有任何明显的速度损失。

更具体地说,我想以整数方式阅读它(即b[0], b[4], ..., b[i * 4])。

这有可能(C#、C++)还是我应该寻找其他方法?

更多背景知识:
我正在尝试加速散列算法(按块对文件进行散列、连接块散列、散列并获取结果散列)。
这个想法是/是采用 SSE3 并“并行”执行 4 个块,这就是为什么我需要这种方式的数据,所以我可以轻松地将数据加载到寄存器中。

我用 C++ 编写的(可调用的)库提供了不错的结果(即快了 4 倍),但重新排序数据会消耗速度增益。

目前我正在逐块读取文件,然后重新排序整数 (C#):

unsafe {
    uint* b = (uint*)buffer.ToPointer() + chunkIndex;
    fixed(byte* blockPtr = chunk) {
        uint* blockIntPtr = (uint*)blockPtr;

        for(int i = 0; i < 9500 * 1024 / 4; i += 4) {
            *(b + 00) = blockIntPtr[i + 0];
            *(b + 04) = blockIntPtr[i + 1];
            *(b + 08) = blockIntPtr[i + 2];
            *(b + 12) = blockIntPtr[i + 3];
            b += 16;
        }
    }
}

chunk 是一个字节数组,chunkIndex 是一个 int,作为方法参数传递。
buffer 是一个 uint32_t* 指针,由我的 C++ 代码分配。

这样做的问题是时间太长了。调用上述代码 4 次大约需要 90 毫秒,而散列需要 3 毫秒。
这个巨大的差异让我觉得有点奇怪,但它会产生正确的哈希值。

【问题讨论】:

    标签: c# c++ hash sse3


    【解决方案1】:

    在 c++ 中我会做类似的事情:

    uint* b = (uint*)buffer;
     for(int i = 0; i < 9500 * 1024; i ++) {
           //read 4 ints
                *(b+i+0)  = blockIntPtr[i + 0];
                *(b+i+1)  = blockIntPtr[i + 1];
                *(b+i+2)  = blockIntPtr[i + 2];
                *(b+i+3)  = blockIntPtr[i + 3];
          //skip next 12 ints
                b += 16;
       }
    

    【讨论】:

    • 您的意思是说整个重新排序在 C++ 中会更快吗?我刚刚测试了它,它需要与 C# 等效的一样长。
    • 如果优化是您的目标,我认为您最好使用无符号长整数而不是整数。阅读 1 长并跳过接下来的 3;如果有帮助,您可以进行一些循环展开。
    • 好吧,我要求的是不需要重新排序整数或不会导致显着速度损失的东西。重新排序花费的时间比散列的时间长 30 倍,这会破坏目的。我尝试展开它,但我得到了相同的时间。至于使用 longs,我不需要 int 边界(我在那里的描述中犯了一个错误(将很快更新),但我的问题中的代码虽然很慢,但我想要的)。
    猜你喜欢
    • 1970-01-01
    • 2021-03-16
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多