首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何对内存中的数据进行重新排序以优化缓存访问?

如何对内存中的数据进行重新排序以优化缓存访问?
EN

Stack Overflow用户
提问于 2014-08-01 15:25:07
回答 2查看 133关注 0票数 1

我想混洗一个大型数据集(类型为List<Record>),然后对其进行多次迭代。通常,混洗列表只会混洗引用,而不是数据。由于频繁的缓存丢失,我的算法的性能受到了极大的影响(3倍)。我可以对混洗后的数据做一个深度拷贝,使其对缓存友好。然而,这将使内存使用量翻倍。

有没有一种更节省内存的方法来对数据进行混洗或重新排序,以便混洗后的数据是缓存友好的?

EN

回答 2

Stack Overflow用户

发布于 2014-08-01 15:31:55

选项1:

使Record成为struct,这样List<Record>就可以在内存中保存连续的数据。

然后直接对其排序,或者(如果记录很大)不直接对列表排序,而是生成一个索引数组(最初只有{0, 1, ..., n - 1}),然后通过让比较器比较索引所引用的元素来对索引进行排序。最后,如果您需要排序的数组,可以通过查看索引来按随机排列的顺序复制元素。

请注意,这可能比直接对结构排序更不适合缓存,但至少它是一次遍历数据,因此它更有可能更快,这取决于结构的大小。如果结构很大,就无法避免这种情况,所以如果不确定Record是否很大,就必须尝试这两种方法,看看直接对记录进行排序是否更有效。

如果您不能更改类型,那么您唯一的解决方案就是以某种方式使它们在内存中连续。要做到这一点,唯一现实的方法是执行初始垃圾收集,然后按顺序分配它们,并祈祷运行时会连续分配它们。如果你不能让它成为一个struct,我想不出还有什么其他的方法可以工作。

如果您认为在中间运行另一个垃圾收集可能会打乱顺序,您可以尝试创建第二个GCHandle数组,其中包含对这些对象的固定引用。我不推荐这样做,但这可能是您目前唯一的解决方案。

选项2:

你真的使用整个记录进行排序吗?这不太可能。如果不是,那么只需提取每条记录中相关的部分,对它们进行排序,然后重新洗牌原始数据。

票数 3
EN

Stack Overflow用户

发布于 2014-08-01 15:36:03

对你来说,最好不要接触这个列表。相反,您可以为list创建一个访问器方法。首先,按随机顺序创建n个元素的数组,例如类似于var arr = [2, 5, .., n-1, 0];的数组

然后创建一个访问方法:

代码语言:javascript
运行
复制
Record get(List<Record> list, int i) {
    return list[arr[i]];
}

通过这样做,列表保持不变,但您在每个索引上都会得到一个随机记录。

编辑:创建随机数组:

代码语言:javascript
运行
复制
int[] arr = new int[n];

// Fill the array with values 1 to n;
for (int i = 0; i < arr.Length; i++)
    arr[i] = i + 1;

// Switch pairs of values for unbiased uniform random distribution:
Random rnd = new Random();
for (int i = 0; i < arr.Length - 1; i++) {
    int j = rnd.Next(i, arr.Length);
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25075004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档