有快速内存访问的技巧吗?

时间:2012-10-15 21:54:05

标签: c++ performance memory pointers

我对C ++编程世界很陌生,很抱歉我的问题:

我得到了一个存储在主存储器(1-D阵列)中的大块数据,我需要经常访问一些数据,我的方法是:

float *x=new float[20];//array to store x;
int *indlistforx=new int[20];//array to store the index of x;
float *databank=new float[100000000];//a huge array to store data

/... fill data to databank.../


for (int i=0;i<N;i++)//where N is a very large number;
 {
  /... write index to indlistforx.../
  getdatafromdatabank(x, indlistforx, databank);
  //Based on the index provided by indlistforx, read data from databank then pass them to x

  /...do something with x.../
  };

是否有任何有效/快速的方法来访问这些数据(x的索引未对齐,并且无法对齐)?

非常感谢提前!

3 个答案:

答案 0 :(得分:3)

你还没有真正展示你是如何访问你的数据库的,所以这些都非常具有推测性:

  • indlistforx数据库中20个索引的列表,所以你要进行20次随机访问?

    • 这些指数的步伐是什么:它们是连续的,还是在一起,或是随机的?
    • 如果它们是连续的或靠近在一起,对它们进行排序可能会有所帮助(因此您按升序阅读以改进预取,并将读取分组从同一个缓存行中)
  • 20个指数的不同群体跳了多少?他们可以重叠吗?

    • 如果它们不能重叠,那么你的数据库被有效地划分为一些块大小,然后处理不同处理器上的每个分区可能会增加你可以使用的有效缓存量(如果你有多个处理器)
    • 如果请求可以重叠并且同时运行它们仍然可以在数据库是只读的情况下工作。如果有任何内容写入数据库,这将成为高速缓存抖动的秘诀
  • 您可以在更高级别重新排序访问以获得更好的缓存行为:更多顺序,更好的空间或时间参考位置?

    • 这与我的第一个建议基本相同,但高于单个indlistforx请求的级别
    • 同样,考虑重新排序它们以有效地划分数据库并尝试多处理器的想法

如果没有看到所有代码(或代表性的样本,我甚至理解这可能太大了),很难再详细介绍。

但是,有一种可能有用的通用技术......它也可能是如此重量级,以至于实施成本超过了节省。

  • 让你的getfromdatabank返回未来/承诺/无论如何,而不是同步完成(或者20个未来的向量,如果那不是太精细)
  • 尝试并行调度大量这些异步请求,或者在单独的线程中(访问未来将是阻塞操作)或者使用事件循环来处理类似于显式协同例程的完成
  • 有一个专用线程聚合来自多个请求的所有数据库访问,并重新排序它们以获得更好的缓存性能

这只有在额外的同步开销由提高的读取性能支配的情况下才有效,并且如果您可以并行地运行许多查询。

答案 1 :(得分:2)

由于需要初始化一个浮点数,你真的应该使用一个std :: vector&lt;&gt;,它不会慢,构造和填充如下:

std::vector< float > databank( 100000000, 0.0f );

加速有几种选择:

1)如果有一个相当大的密钥(索引)重用,那么你可以使用某种缓存或记忆策略。 有关示例,请参阅http://www.boost.org/doc/libs/1_51_0/libs/flyweight/doc/index.html

2)您可以使用say std :: async()将处理拆分为多个线程。

3)确保您的编译器已启用simd指令(在x86上为sse)并正在使用它们。如果不使用编译器内在函数强制使用simd。这将使近4倍的改善。

答案 2 :(得分:1)

问题不在于您如何代表databank。问题是你如何使用它。在短时间内随机访问广泛分离的databank部分会破坏您的表现。 getdatafromdatabank(x, indlistforx, databank) indlistforx indlistforx几乎可以保证性能不佳。由databank启用的随机访问会带来显着的性能损失。如果随机访问绝对必要,因为使用databank的算法如何工作,那只是你必须支付的价格。

如果您可以修改算法,以便在getdatafromdatabank中访问连续的内存块,您将获得更好的性能。更改x[0],以便仅指定第一个索引(要加载到x的元素的索引)而不是数组20索引。

是否有x大小为20的原因?如果您几乎无法将输出databank数组和x的相关块保留在1级缓存中,您将获得最佳性能。如果{{1}}的大小超出此最佳大小,性能将开始降低,并且可能会显着降低。