我应该使用简单的类还是高维矩阵?
Posted
技术标签:
【中文标题】我应该使用简单的类还是高维矩阵?【英文标题】:Should I use simple classes or a highly dimensional matrix? 【发布时间】:2016-10-09 20:46:50 【问题描述】:这里是 C++ 新手!我想模拟一个包含补丁、包含个体、包含染色体、包含基因的群体。
在 C++ 中使用一系列简单的类与使用高维矩阵的优缺点是什么?通常,访问内存插槽的时间是否因两种技术而异?
高维矩阵
可以制作“向量的向量的向量”(或 C 风格的高维整数数组)并使用
访问内存中的任何基因for (int patch=0;patch<POP.size();patch++)
for (int ind=0;ind<POP[patch].size();patch++)
for (int chrom=0;chrom<POP[patch][ind].size();chrom++)
for (int gene=0;gene<POP[patch][ind][chrom].size();gene++)
POP[patch][ind][chrom][gene];
简单类系列
人们可以使用一系列简单的类并通过
访问内存中的任何基因for (int patch=0;patch<POP->PATCHES.size();patch++)
for (int ind=0;ind<POP->PATCHES[patch]->INDIVIDUALS.size();patch++)
for (int chrom=0;chrom<POP->PATCHES[patch]->INDIVIDUALS[ind]->CHROMOSOMES.size();chrom++)
for (int gene=0;gene<POP->PATCHES[patch]->INDIVIDUALS[ind]->CHROMOSOMES[chrom]->GENES.size();gene++)
POP->PATCHES[patch]->INDIVIDUALS[ind]->CHROMOSOMES[chrom]->GENES[gene];
【问题讨论】:
是patch
、ind
、chrom
和 gene
只是整数索引,而不是像 std::string
s 这样的东西吗?
是的!我试图通过写出for循环并定义patch
、ind
、chrom
和gene
的对象类型来澄清这一点
【参考方案1】:
虽然高维矩阵可行,但请考虑您可能希望向个人添加更多信息。它可能不仅有染色体,还有年龄、兄弟姐妹、父母、表型等。然后很自然地有一个class Individual
,它可以包含所有这些信息以及它的染色体列表。使用类会将相关信息组合在一起。
【讨论】:
谢谢。这是正确的,我最终可能愿意编写一些特定于类的函数(在 python 中称为方法,不确定它们在 C++ 术语中是否具有相同的名称)。我主要关心访问内存插槽的时间。我是否应该期望“一系列简单类”方法更慢? 使用类并不一定意味着它更慢。编写一个正确且易于理解的实现应该是您的首要任务,优化是其次。在优化时,确定大部分 CPU 时间都花在了哪里。是不是对基因进行了某种操作?然后你要确保包含基因的数据在内存中是靠得很近的。class Chromosome vector<Gene> genes; ;
仍然确保基因靠近。事实上,如果每个类只包含一个vector<>
成员,与一个大的vector<vector<vector<vector<...>>>>
相比,没有开销。【参考方案2】:
虽然我大体上同意@g-sliepen 的回答,但还有一点你应该知道:
C++ 使您能够区分接口和类型。您可以将类型 abstract 留给您的代码的用户(即使只有您自己),并提供一组有限的操作。
使用此模式,您可以在以后完全更改实现(例如,回到向量以进行并行计算等),而无需更改使用它的代码(例如,具体模拟)。
【讨论】:
【参考方案3】:我不会介绍已经提出的建议,因为将您的 individual
实体存储为一个具有所有相关字段的类通常是一个好主意,但我将只解决您的第一个建议:
使用std::vector<std::vector<std::vector<std::vector<type>>>>
之类的东西(除了一般处理起来很痛苦)的问题是,虽然包围结构的整体std::vector
具有连续存储(只要您不存储@987654321 @即)内部向量彼此或其他元素不连续。
因此,如果您在结构中存储大量数据并且需要尽可能快地访问和迭代,那么这种存储方法并不理想 - 它还会使迭代整个结构的问题变得复杂。
当您需要快速迭代和随机访问时,存储大型多维“矩阵”(我想在这种情况下技术上是 4 级张量)的一个很好的解决方案是在某些 @ 中围绕单个 std::vector
编写包装器987654322@ 配置,这样您的所有数据都存储为一个连续的块,您可以通过单个循环或调用std::for_each
(例如)对其进行迭代。然后,您访问该结构所使用的每个索引将依次对应于patch
、ind
、chrom
和gene
。
如果您不想自己编写包装器代码,则可以处理此问题的预构建数据结构示例是 boost::multi_array
。
【讨论】:
【参考方案4】:有两种主要的方法来做多维数组。向量的向量(又名锯齿状数组)和真正的多维数组 - n 维立方体。例如,使用后一种意味着所有染色体都具有相同数量的基因,并且每个个体都具有相同数量的染色体。如果您可以接受这些限制,您将获得一些优势,例如连续内存存储。
【讨论】:
以上是关于我应该使用简单的类还是高维矩阵?的主要内容,如果未能解决你的问题,请参考以下文章
如何处理 sklearn 随机森林中的类不平衡。我应该使用样本权重还是类权重参数