beachmat 2.12.0
注:本文档参考第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 >
.我们使用唯一指针来控制所有权,并在函数结束时平滑地处理销毁和内存释放。std::异常
类,其中包含有信息的错误消息。这些应该被最终用户代码优雅地捕获和处理,否则可能会发生分割错误。参见中的错误处理机制Rcpp如何处理这些异常。的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();
的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]
零索引,附加的要求是最后>=第一个
.
的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]
零索引,附加的要求是最后>=第一个
.
的get ()
方法在行的矩阵项上返回双精度值r
和列c
.这两个r
而且c
应该是零索引的整数吗[0, nrow)
而且[0, ncol)
分别。
Double val = dptr->get(r, /* size_t */ c /* size_t */);
如果对象在
是一个Rcpp: NumericVector:: iterator
实例中,矩阵项将被提取为双精度值。如果是Rcpp: IntegerVector:: iterator
实例中,矩阵项将提取为从双精度类型进行隐式转换的整数焦度
.它也是可能的使用Rcpp: LogicalVector:: iterator
,但请参阅警告下面.
的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)
指向的可访问元素在
.
该方法将提取列主格式的值。也就是说,如果要计算包含所选列和所选行范围的子矩阵,则该子矩阵将以列-主形式可用在
.
此方法不返回任何值。
的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
.
此方法不返回任何值。
要创建逻辑、整数和字符矩阵,包括以下头文件:
#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:: iterator
S代表其他任何东西logical_matrix
访问。character_matrix
数据,我们不返回原始数据const char *
指向c风格字符串的指针。相反,Rcpp:字符串
类的使用是因为它提供了一个方便的底层包装器CHARSXP
.这确保字符串存储在R的全局缓存中,并适当地防止垃圾收集。以下矩阵类是由API原生支持的:
矩阵
,dgeMatrix
,dgCMatrix
矩阵
矩阵
,lgeMatrix
,lgCMatrix
矩阵
API也将支持本机DelayedMatrix
使用上述矩阵作为后端的对象而且只包含子集或移位操作的。本机支持任意用户提供的矩阵是可能的,参见在这里有关详情及HDF5Array举个例子。
对于所有其他矩阵,API通过块处理机制间接支持数据访问。这涉及到调用R,以将矩阵的一个块(包含所请求的行或列)实现为密集的连续数组。类中的方法控制块的大小,以便对同一块中的行/列的进一步请求不涉及对r的新调用DelayedArray包,看到blockGrid ?
获取详细信息。
额外的笔记
收益率
可以用方法获取原件Rcpp: RObject
用于输入RcppArmadillo或RcppEigen.该功能通常仅限于基本矩阵,尽管这些库中对稀疏矩阵的支持也有限。对于特定的矩阵表示,可以使用特殊的方法来提高列级数据访问的效率。
dgeMatrix
实例存储为密集数组,因此可以通过返回每个列的开头的迭代器来访问列而不复制。dgCMatrix
,列稀疏格式允许我们直接访问每列的非零值(及其行索引),而不需要复制。的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
在一些人为的场景中破坏。获取列值的迭代器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{//对所有元素执行操作。}
一些应用程序需要表示包括0在内的所有元素,例如,当后续数组需要通过行索引访问时。方法可以确保获得密集数组的迭代器const_column
与allow_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
对象将被创建。
的克隆()
方法返回指向对象的唯一指针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为连续的行/列访问进行了优化。
额外的笔记