我应该使用简单的类还是高维矩阵?

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];
            
        
       

【问题讨论】:

patchindchromgene 只是整数索引,而不是像 std::strings 这样的东西吗? 是的!我试图通过写出for循环并定义patchindchromgene的对象类型来澄清这一点 【参考方案1】:

虽然高维矩阵可行,但请考虑您可能希望向个人添加更多信息。它可能不仅有染色体,还有年龄、兄弟姐妹、父母、表型等。然后很自然地有一个class Individual,它可以包含所有这些信息以及它的染色体列表。使用类会将相关信息组合在一起。

【讨论】:

谢谢。这是正确的,我最终可能愿意编写一些特定于类的函数(在 python 中称为方法,不确定它们在 C++ 术语中是否具有相同的名称)。我主要关心访问内存插槽的时间。我是否应该期望“一系列简单类”方法更慢? 使用类并不一定意味着它更慢。编写一个正确且易于理解的实现应该是您的首要任务,优化是其次。在优化时,确定大部分 CPU 时间都花在了哪里。是不是对基因进行了某种操作?然后你要确保包含基因的数据在内存中是靠得很近的。 class Chromosome vector&lt;Gene&gt; genes; ; 仍然确保基因靠近。事实上,如果每个类只包含一个vector&lt;&gt; 成员,与一个大的vector&lt;vector&lt;vector&lt;vector&lt;...&gt;&gt;&gt;&gt; 相比,没有开销。【参考方案2】:

虽然我大体上同意@g-sliepen 的回答,但还有一点你应该知道:

C++ 使您能够区分接口和类型。您可以将类型 abstract 留给您的代码的用户(即使只有您自己),并提供一组有限的操作。

使用此模式,您可以在以后完全更改实现(例如,回到向量以进行并行计算等),而无需更改使用它的代码(例如,具体模拟)。

【讨论】:

【参考方案3】:

我不会介绍已经提出的建议,因为将您的 individual 实体存储为一个具有所有相关字段的类通常是一个好主意,但我将只解决您的第一个建议:

使用std::vector&lt;std::vector&lt;std::vector&lt;std::vector&lt;type&gt;&gt;&gt;&gt; 之类的东西(除了一般处理起来很痛苦)的问题是,虽然包围结构的整体std::vector 具有连续存储(只要您不存储@987654321 @即)内部向量彼此或其他元素不连续。

因此,如果您在结构中存储大量数据并且需要尽可能快地访问和迭代,那么这种存储方法并不理想 - 它还会使迭代整个结构的问题变得复杂。

当您需要快速迭代和随机访问时,存储大型多维“矩阵”(我想在这种情况下技术上是 4 级张量)的一个很好的解决方案是在某些 @ 中围绕单个 std::vector 编写包装器987654322@ 配置,这样您的所有数据都存储为一个连续的块,您可以通过单个循环或调用std::for_each(例如)对其进行迭代。然后,您访问该结构所使用的每个索引将依次对应于patchindchromgene

如果您不想自己编写包装器代码,则可以处理此问题的预构建数据结构示例是 boost::multi_array

【讨论】:

【参考方案4】:

有两种主要的方法来做多维数组。向量的向量(又名锯齿状数组)和真正的多维数组 - n 维立方体。例如,使用后一种意味着所有染色体都具有相同数量的基因,并且每个个体都具有相同数量的染色体。如果您可以接受这些限制,您将获得一些优势,例如连续内存存储。

【讨论】:

以上是关于我应该使用简单的类还是高维矩阵?的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch深度学习基础之Tensor

如何处理 sklearn 随机森林中的类不平衡。我应该使用样本权重还是类权重参数

我应该继承列表还是创建具有列表作为属性的类?

你的类应该实现 ActionListener 还是使用匿名 ActionListener 类的对象

数组应该被认为是水平结构还是垂直结构

我应该使用监听器还是观察器?