1输入API的概述

注:本文档参考第2版beachmatAPI,它仍然受到支持,但不再处于积极的开发中。2021欧洲杯体育投注开户鼓励编写新代码的开发人员使用版本3,它更加简化。

本文档介绍了beachmat用于访问R矩阵中的数据的API。我们将演示数值矩阵上的API,尽管相同的语义用于其他类型的矩阵(例如,逻辑、整数、字符)。首先,我们包含相关的头文件:

# include“beachmat / numeric_matrix.h”

一个双精度矩阵对象质素在c++中通过传递饱和度指数结构从打电话给create_numeric_matrix

自动DPTR = beachmat::create_numeric_matrix(dmat);

属性的对象创建唯一指针numeric_matrix基类。中实际实例化的确切派生类取决于矩阵的类型质素,尽管用户级函数的行为不受此细节的影响。

额外的笔记

  • 汽车关键字只是避免了需要写入返回指针的完整类型,即std:: unique_ptr < beachmat: numeric_matrix >.我们使用唯一指针来控制所有权,并在函数结束时平滑地处理销毁和内存释放。
  • 的异常,API会很高兴地抛出std::异常类,其中包含有信息的错误消息。这些应该被最终用户代码优雅地捕获和处理,否则可能会发生分割错误。参见中的错误处理机制Rcpp如何处理这些异常。

2查询矩阵信息

get_nrow ()方法返回矩阵中的行数:

Size_t nrow = dptr->get_nrow();

get_ncol ()方法返回矩阵中的列数:

Size_t ncol = dptr->get_ncol();

get_class ()方法返回指向的矩阵表示形式的类焦度,而get_package ()方法返回定义该类的包1以防两个包定义相同的类名。

Std::string mat_type = dptr->get_class();

产量()方法返回用于创建的原始R矩阵焦度

Rcpp:: object original = dptr->yield();

3.基础数据提取

3.1从列

get_col ()方法填充迭代器到一个Rcpp具有来自列的值的向量c矩阵的。至少应该有nrow可访问元素,即*在而且* (+ nrow-1)应该是有效的条目。

焦度- > get_col (c / * / * Rcpp size_t * /::向量::iterator * /);

方法指定列范围的提取第一个而且最后的参数。这个会填满列的值c从行第一个持续1.至少应该有last-first可访问元素,即*在而且* (+ last-first-1)应该是有效的条目。

焦度- > get_col (c / * size_t * / / * Rcpp::向量::iterator * /, / * size_t去年/ * size_t * / * /);

这两个方法都不会返回任何值。请注意,c应该是一个零索引的整数[0, ncol).类似地,两个第一个而且最后的应该在[0, nrow]零索引,附加的要求是最后>=第一个

3.2从行

get_row ()方法接受一个迭代器到一个Rcpp向量,然后用row的值填充它r.至少应该有ncol可访问元素,即*在而且* (+ ncol-1)应该是有效的条目。

焦度- > get_row (r / * / * Rcpp size_t * /::向量::iterator * /);

属性指定行范围的提取第一个而且最后的参数。这个会填满值在行中r从列第一个持续1.至少应该有last-first可访问元素,即*在而且* (+ last-first-1)应该是有效的条目。

焦度- > get_row (r / * size_t * / / * Rcpp::向量::iterator * /, / * size_t去年/ * size_t * / * /);

这两个方法都不会返回任何值。再一次,r应该是一个零索引的整数[0, nrow).这两个第一个而且最后的应该在[0, ncol]零索引,附加的要求是最后>=第一个

3.3从单个细胞

get ()方法在行的矩阵项上返回双精度值r和列c.这两个r而且c应该是零索引的整数吗[0, nrow)而且[0, ncol)分别。

Double val = dptr->get(r, /* size_t */ c /* size_t */);

3.4类型转换

如果对象是一个Rcpp: NumericVector:: iterator实例中,矩阵项将被提取为双精度值。如果是Rcpp: IntegerVector:: iterator实例中,矩阵项将提取为从双精度类型进行隐式转换的整数焦度.它也是可能的使用Rcpp: LogicalVector:: iterator,但请参阅警告下面

4多重数据提取

4.1从列

get_cols ()方法填充迭代器到一个Rcpp由矩阵多列的值组成的向量。的idx迭代器应该指向一个长度为整数的数组n,包含用于提取的列索引。索引应该是从零开始的和严格意义上的增加,即不重复。

dptr->get_cols(idx, /* Rcpp::IntegerVector::iterator */ n, /* size_t */ in, /* Rcpp::Vector::iterator */ first, /* size_t */ last /* size_t */);

中的值的范围(首先,最后)提取。如果第一个而且最后的未指定时,范围将默认为[0, nrow).因此,至少应该有n * (last-first)指向的可访问元素

该方法将提取列主格式的值。也就是说,如果要计算包含所选列和所选行范围的子矩阵,则该子矩阵将以列-主形式可用

此方法不返回任何值。

4.2从行

get_rows ()方法填充迭代器到一个Rcpp由矩阵的多行值组成的向量。的idx迭代器应该指向一个长度为整数的数组n,包含用于提取的列索引。索引应该是从零开始的和严格意义上的增加,即不重复。

dptr->get_rows(idx, /* Rcpp::IntegerVector::iterator */ n, /* size_t */ in, /* Rcpp::Vector::iterator */ first, /* size_t */ last /* size_t */);

中的值的范围(首先,最后)提取。如果第一个而且最后的未指定时,范围将默认为[0, ncol).因此,至少应该有n * (last-first)指向的可访问元素

就像get_cols (),此方法将以列主格式提取值。也就是说,如果要计算包含所选列和所选行范围的子矩阵,则该子矩阵将以列-主形式可用.注意,这意味着中连续的元素同一行!相反,它们将来自同一列,但只来自指定的行idx

此方法不返回任何值。

5推广到其他矩阵

5.1其他数据类型

要创建逻辑、整数和字符矩阵,包括以下头文件:

#include "beachmat/logical_matrix.h" #包括"beachmat/integer_matrix.h"

逻辑矩阵的调度函数相应变化lmat,整数矩阵imat或者字符矩阵cmat.的惟一指针* _matrix合适的类型。

//创建std::unique_ptr auto lptr=beachmat::create_logical_matrix(lmat);//创建std::unique_ptr auto iptr=beachmat::create_integer_matrix(imat);//创建std::unique_ptr auto cptr=beachmat::create_character_matrix(cmat);

对于每一种矩阵类型都有相应的方法。

对于整数矩阵和逻辑矩阵,get ()将返回一个整数。可以是前面描述的任何类型numeric_matrix对象。

对于字符矩阵,所有迭代器都应该是类型Rcpp: StringVector:: iterator,get ()将返回一个Rcpp:字符串

额外的笔记

  • 如果是一个Rcpp: LogicalVector:: iterator对于非逻辑矩阵,结果可能不像预期的那样。为numeric_matrix实例中的双精度值(1,1)在c++中由于双整数强制转换而被强制为零。这与R中非零值的行为不一致,非零值被强制为真正的.为integer_matrix实例中,整数值不强制为{0,1}当他们被分配到*在.因此,即使解释是正确的,所产生的向量也不会等价于的结果as.logical调用。作为一般规则,使用它是不明智的Rcpp: LogicalVector:: iteratorS代表其他任何东西logical_matrix访问。
  • 当访问character_matrix数据,我们不返回原始数据const char *指向c风格字符串的指针。相反,Rcpp:字符串类的使用是因为它提供了一个方便的底层包装器CHARSXP.这确保字符串存储在R的全局缓存中,并适当地防止垃圾收集。

5.2可供选择的矩阵表示

以下矩阵类是由API原生支持的:

  • 数字:矩阵dgeMatrixdgCMatrix
  • 整数:矩阵
  • 逻辑:矩阵lgeMatrixlgCMatrix
  • 性格:矩阵

API也将支持本机DelayedMatrix使用上述矩阵作为后端的对象而且只包含子集或移位操作的。本机支持任意用户提供的矩阵是可能的,参见在这里有关详情及HDF5Array举个例子。

对于所有其他矩阵,API通过块处理机制间接支持数据访问。这涉及到调用R,以将矩阵的一个块(包含所请求的行或列)实现为密集的连续数组。类中的方法控制块的大小,以便对同一块中的行/列的进一步请求不涉及对r的新调用DelayedArray包,看到blockGrid ?获取详细信息。

额外的笔记

  • 对于数值矩阵,beachmat不支持高级矩阵操作,如加法、乘法或各种因式分解。相反,收益率可以用方法获取原件Rcpp: RObject用于输入RcppArmadilloRcppEigen.该功能通常仅限于基本矩阵,尽管这些库中对稀疏矩阵的支持也有限。

6专门的数据提取

6.1概述

对于特定的矩阵表示,可以使用特殊的方法来提高列级数据访问的效率。

  • 普通矩阵或dgeMatrix实例存储为密集数组,因此可以通过返回每个列的开头的迭代器来访问列而不复制。
  • 如果下面的矩阵是adgCMatrix,列稀疏格式允许我们直接访问每列的非零值(及其行索引),而不需要复制。

const_column类提供了方便的包装器,以便在可能的情况下利用这些优化。

#include "beachmat/utils/const_column.h" //需要一个get(),因为unique_ptr是不可复制的。beachmat: const_column < beachmat: numeric_matrix > col_holder (dptr.get ());

填满方法将指示const_column对象获取相关列,如果表示形式支持,则利用无复制方法。对于其他矩阵,它简单地调用get_col ()对其内部存储执行复制。

col_holder。填满( c /* size_t */, first /* size_t */, last /* size_t */ );

第一个而且最后的参数是可选的,其行为与前面描述的相同。

额外的笔记

  • 人的一生const_column实例的值不应超过numeric_matrix它是用它来建造的。这是因为前者持有指向后者的指针,后者在销毁时将不再有效。的const_column还保留了指向底层r管理数据的迭代器,这些数据可能会使其失效numeric_matrix在一些人为的场景中破坏。

6.2解释迭代器

获取列值的迭代器get_values

Rcpp:: NumericVector:: iterator val = col_holder.get_values ();

获取每个值的行索引的迭代器get_indices

Rcpp:: IntegerVector:: iterator idx = col_holder.get_indices ();

迭代器所指向的值的数量是通过get_n

size_t n = col_holder.get_n ();

显然,稀疏矩阵不会在by指向的值数组中存储任何零get_values (),在by指向的数组中也不会出现0的行下标get_indices ().这可能需要也可能不需要一些定制代码来最大限度地利用稀疏性:

if (col_holder.is_sparse()){//快速处理非零元素。} else{//对所有元素执行操作。}

6.3进一步的选择

一些应用程序需要表示包括0在内的所有元素,例如,当后续数组需要通过行索引访问时。方法可以确保获得密集数组的迭代器const_columnallow_sparsity参数关闭:

Beachmat::const_column< Beachmat::numeric_matrix> col_holder(dptr.get(), false);

这样做会迫使const_column使用get_col ()用于访问稀疏矩阵,而不是获取原始结构的迭代器。然而,密集矩阵的无复制优化仍然是有效的。

对于非稀疏矩阵,调用get_indices ()将导致用连续的迭代器填充内部数组。一个人可以在许多人之间共享这个数组const_column通过调用get_indices ()在构建副本之前:

beachmat: const_column < beachmat: numeric_matrix > col_holder (dptr.get ());col_holder.get_indices ();//有效的“静态”索引。//在不重新生成索引的情况下复制任意数量的索引。汽车holder_copy = col_holder;

这可以节省一些内存const_column对象将被创建。

7克隆矩阵实例

克隆()方法返回指向对象的唯一指针numeric_matrix与所指向的类型相同的实例焦度

自动dptr_copy = dptr->克隆();

这有时是有用的,例如,当同时需要对同一个矩阵进行行和列访问时。在这种情况下,行特定的设置在单个numeric_matrix实例(例如,用于HDF5缓存)将排除有效的列提取,反之亦然。通过使用两个单独的实例进行行和列访问,可以避免这些问题。

克隆还支持对相同矩阵数据的多线程访问。通常,得到*方法在beachmat不是线程安全的。一些方法使用缓存的类成员来提高效率,同时调用会导致竞争条件。调用函数负责协调跨线程的数据访问。为此目的,克隆方法生成指向对象的唯一指针* _matrix实例,它可以并发地在另一个线程中使用。这是相当便宜的,因为底层矩阵数据不被复制。

一个并行化的例子beachmat使用OpenMP的代码可能是这样的:

#pragma omp parallel num_threads(nthreads) {beachmat::numeric_matrix* rptr=NULL;std:: unique_ptr < beachmat: numeric_matrix > uptr = nullptr;If (omp_get_thread_num()==0) {rptr=dptr.get();} else {uptr=dptr->克隆();rptr = uptr.get ();} const size_t NC=rptr->get_ncol();Rcpp: NumericVector输出(rptr - > get_nrow ());for (size_t col=0;坳<数控;++col){//在这里执行并行操作。 rptr->get_col(col, output.begin()); } }

平行区域的开始使用现有的焦度并在其他线程中克隆一个新的矩阵。并行化的循环然后使用rptr在缓存的变量中避免竞争条件。注意,静态调度可能比其他调度类型快,因为在beachmat为连续的行/列访问进行了优化。

额外的笔记

  • 对于共同体定义的矩阵,beachmat可以使用外部链接来本机访问数据。2021欧洲杯体育投注开户相应共享库的开发人员应该确保他们的例程依赖于线程安全的库。例如,HDF5库不是线程安全的,所以HDF5Array输入可能会破坏OpenMP代码。不可否认,这是相当令人沮丧的,因为hdf5支持的矩阵通常用于最需要并行处理的大型数据集。作为一种解决方法,我们建议在R级上使用BiocParallel