首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更好的GSL gsl_vector内存管理

更好的GSL gsl_vector内存管理
EN

Stack Overflow用户
提问于 2013-04-13 14:25:04
回答 2查看 2.1K关注 0票数 0

当我用C++编写线性代数程序时,我使用Armadillo库。它基于模板,它提供了一种方法来定义任何长度的向量,这些向量不一定需要额外的内存分配,因为它们在编译时被静态地分配了一个适当的内存缓冲区。当我使用arma::Col<double>::fixed<3>时,编译器会动态创建一个“新类型”,这样向量就包含了整整3倍的缓冲区。

现在我正在用C语言编写一个线性代数程序,我正在使用GNU科学图书馆(GSL)。为了实例化一个3D向量,我需要:返回一个gsl_vector_alloc(3)gsl_vector*。问题是,此操作导致动态分配一小部分内存,并且在程序运行时发生了数百万次。我的程序正在浪费大量资源来执行数以千万计的malloc/free操作。

我检查了gsl_vector的内部结构

代码语言:javascript
复制
typedef struct
{
   size_t size;
   size_t stride;
   double * data;
   gsl_block * block;
   int owner;
} gsl_vector;

为了使库正确工作,data应该指向向量的第一个元素,通常在gsl_block结构中,如下所示:

代码语言:javascript
复制
typedef struct
{
   size_t size;
   double * data;
} gsl_block;

它包含另一个data指针。因此,为了实例化一个简单的3D向量,会出现以下malloc序列:

  1. gsl_vector结构是malloc'd (x86_64上大约有40个字节)。
  2. gsl_block结构是malloc'd (16字节),gsl_vector的block指针被设置为刚刚分配的gsl_block的内存地址。
  3. 一个3倍的数组是malloc'd,它的内存地址被分配给两个data指针( gsl_block中的和gsl_vector中的)。

通过删除两个malloc,我获得了40%的性能增益。我创建了自定义的gsl_vector创建例程,该例程分配一个3倍的数组,并将gsl_vectordata指针设置为该数组的地址。然后返回一个gsl_vector (不是指针)。

但是这样做,我仍然得到了数百万的malloc(3 * sizeof(double))操作。

我没有设法将3的数组“嵌入”到gsl_vector结构中,因为如果data指针指向结构本身内的某个东西(hacky!),那么当向量被复制到其他地方时,指针就不再有效了!

你有什么想法(除了切换到C++或滚动我自己的线性代数库)?我愿意接受任何建议。

EN

回答 2

Stack Overflow用户

发布于 2013-04-13 16:42:14

在我看来,您似乎误解了gls_block数据结构的用途。在我看来,您应该使用它在gsl_block数据结构中分配一大块数据,然后将该块分割成多个gsl_vector。如果通过分配一个数组来一次分配所有的gsl_vector,那么您就快到了。在初始化过程中,您只需要对malloc进行两次调用,并进行一些簿记。

这会给你带来什么影响,那就是你必须事先精确地考虑你需要哪一个gsl_vector。但是,当您使用一种没有内置垃圾收集的语言时,这就是要付出的“代价”。如果您对此进行投资,大多数情况下,它具有构造代码的优点,您可能会了解到如何组织计算。

票数 4
EN

Stack Overflow用户

发布于 2013-04-13 16:43:07

C太原始了,不能很好地做到这一点。

如果您需要使用GSL的函数,您可能仍然可以使用C++ Armadillo向量和矩阵。

例如,您可以通过.memptr()成员函数获得指向向量或矩阵使用的内存的指针。这也适用于固定大小的矩阵/向量。

或者,您可以告诉Armadillo使用已经分配的内存块,方法是在向量或矩阵施工期间给它一个指针。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15988836

复制
相关文章

相似问题

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