2012-10-15 35 views
0

我很新的C++编程世界的,对不起,我amatuerish问题:有没有快速内存访问的技巧?

我获取存储在主存储器(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的指数是不对齐的,它是不可能被排列)?

非常感谢提前!

+2

'new float [100000000];'?可能你住在70年代... – 2012-10-15 21:58:21

+2

我不太明白你的问题。你的代码的某些部分运行速度太慢了吗? –

+0

我不明白这个问题。什么是'x'? – Claudix

回答

2

由于浮法需要初始化,你真的应该用std :: vector的<>,它不是慢,构造和填充像这样:

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

有用于高速化的几个选项:

1)如果有一个合理的大键(索引)重用,那么你可以使用某种缓存或记忆策略。例如, 参见http://www.boost.org/doc/libs/1_51_0/libs/flyweight/doc/index.html

2)你可以使用std :: async()将处理分成多个线程。

3)确保你的编译器有SIMD指令(x86上的sse)打开并使用它们。如果不通过使用编译器内在函数强制使用simd。这将允许接近4倍的改善。

+0

非常感谢,我会尝试你的建议,至于SIMD,是的,我的程序是用AVX选项编译的。 – user0002128

+1

我不会downvote,但这个答案本质上是不正确的。切换到矢量不会有帮助。 'std :: vector '和'float *'之间的唯一区别是安全。速度? No. Vectors只是一个原始指针周围的RAII安全包装。罪魁祸首是随机访问;切换到矢量不会改变这一点。什么将改变,就是摆脱随机访问。 –

3

你还没有真正显示你如何访问您的数据库,所以这是大家很投机:

  • indlistforx 20个指数到数据库的清单,让你做20个随机访问?

    • 这些指标的进展如何:它们是连续的还是紧密的,还是随机的?
    • ,如果他们连续或并拢,将它们分类可以帮助(所以你按升序提高预取读,分组从同一缓存行的读取一起)
  • 做了多少不同20个指数群组跳跃?它们可以重叠吗?

    • ,如果他们不能重叠,所以你的数据库被有效分割成一些块大小,然后处理不同的处理器上的每个分区可以增加有效的缓存可以使用(如果您有多个处理器)
    • 如果请求可以重叠同时运行它们,如果数据库是只读的,仍然可以工作。如果有什么写入数据库,这将成为高速缓存抖动
  • 您可以在更高层次上得到更好的缓存行为重新排序的访问配方:多个顺序,更好的参考空间或时间局部性?

    • 这是基本相同,我的第一个建议,而是一个indlistforx请求的级别
    • 以上类似地,可以考虑重新安排他们有效地分割数据库,并尝试在多处理器的想法

没有看到所有的代码(或有代表性的样本,我的理解甚至可能太大)很难进入任何更多的细节。

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

  • 让你getfromdatabank回到未来/诺/不管,而不是完成同步(或20个期货载体,如果这不是太细粒度)
  • 尝试派遣大量的这些并行异步请求,无论是在单独的线程(访问期货将是一个阻塞操作),或使用事件循环来处理完成,像明确的协同例程
  • 有一个专用线程聚集所有数据库从多个请求访问,并重新排序获得更好的缓存性能

只有当额外的同步开销受改进的读取性能支配时,以及是否可以有效地并行运行多个查询时,这才可以工作。

+0

+1。这种随机访问是真正的罪魁祸首。 –

+0

谢谢,就我而言,它是随机访问的数据,但没有重叠。 – user0002128

+0

非常感谢您的建议,是的,我无法发布代码的原因是因为我广泛使用simd内部函数和CUDA代码,所以代码太长,大部分代码与随机内存访问无关。 – user0002128

1

问题不在于你如何表示你的databank。问题在于你如何使用它。在短时间内随机访问您的databank广泛分离的部分将会导致您的性能下降。您的getdatafromdatabank(x, indlistforx, databank)indlistforx几乎可以保证糟糕的表现。由该indlistforx启用的随机访问带来显着的性能损失。如果随机访问是绝对必要的,因为使用您的databank的算法的工作方式如此,这只是您必须付出的代价。

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

x的大小是否有20?如果您仅仅将输出x阵列和databank的相关块保留在1级缓存中,您将获得最佳性能。如果x的尺寸增加超出此最佳尺寸,性能将开始下降,并可能显着下降。

+0

我必须使用随机访问,我可以重新安排数据库以允许基于块的访问,但是这会降低代码的其他部分的性能,并且折衷不是很漂亮(实际上我有这个确切原因让它随机访问数据库是为了让我的代码的其他部分能够“大块地”访问数据),这就是为什么我必须坚持随机访问大块数据,我只想知道是否有任何数据提高随机访问性能的方法,我想知道多线程是否会有很大帮助? – user0002128