编译古巴库

Compiling the Cuba library

我目前需要使用 Julia 中的 Cuba 库来计算一些三维积分。事实上,我需要在单个 运行 中多次使用 cuhre 函数,因为我需要这样做。但是,这有大量分配的问题。

举个例子,我可以尝试积分 f(x1,x2,x3) = x1*x2*x3,这给了我结果(当我使用@time 快速查看性能时)

julia> @time cuhre((x,f)->f[1]=x[1]*x[2]*x[3],3,1)
0.101907 seconds (115.82 k allocations: 5.809 MiB)
Component:
1: 0.125 ± 1.5700924586837752e-16 (prob.: 0.0)
Integrand evaluations: 381
Number of subregions:  2
Note: The desired accuracy was reached

问题是分配只能加起来,这意味着我可以快速达到数千万的分配和 GiB。由于 Julia 似乎没有释放内存的方法,我更仔细地查看了 Cuba.jl 包,发现它包装了 C 库 Cuba(使用 ccall)。我看了看代码 (The cuhre part in the C labrary),发现它从未释放分配的内存。更准确地说,我看到了

的使用(在 Integrate.c 中)
RuleAlloc(t);

FrameAlloc(t, Master);

MemAlloc(cur, poolsize);

指向指针

This *t

Pool *cur = NULL, *pool;

但是,我似乎释放内存的唯一情况是出现中止时:

abort:
  while( (pool = cur) ) {
    cur = cur->next;
    free(pool);
  }
  FrameFree(t, Master);
  RuleFree(t);

  StateRemove(t);

  return fail;

而当程序 运行 运行顺利时它永远不会。

所以我考虑手动修改此函数并添加释放自己的内存并git-克隆the cuba library。但是,我正在努力编译最新版本 (4.1)。我试着按照给出的(很少的)说明进行操作,即输入

$ ./configure
$ ./makeshared.sh #

但是第二个不行

$ ./makeshared.sh #
bash: ./makeshared.sh: Aucun fichier ou dossier de ce type

(没有该类型文件夹的文件)。我寻找解决方案并找到 this topic,并尝试了给出的各种答案(对 运行 demo-c.c 文件),但 none 似乎有效,主要是因为文件中不再有 libcuba.a 文件。

因为这有任何帮助,这是我在编译演示时遇到的错误-c.c 文件

$ gcc -o demo-c.exe demo-c.c -lm
/tmp/ccAYMLVk.o : Dans la fonction « main » :
demo-c.c:(.text+0x123) : référence indéfinie vers « Vegas »
demo-c.c:(.text+0x226) : référence indéfinie vers « Suave »
demo-c.c:(.text+0x343) : référence indéfinie vers « Divonne »
demo-c.c:(.text+0x439) : référence indéfinie vers « Cuhre »
collect2: error: ld returned 1 exit status

(对...的未定义引用)。在 1.1 版本中,使用命令

解决了这个问题
gcc -o demo-c.exe demo-c.c ../libcuba.a -lm

但它显然不再有效,因为不再有这样的文件。

一般来说,如果您对 Cuba C 库有任何问题,最好的办法是联系作者:https://wwwth.mpp.mpg.de/members/hahn/. If an issue is fixed upstream, it'll be eventually included in the Cuba.jl Julia wrapper。


了解您对内存分配的担忧是错误的,原因有几个:

  1. 您没有正确执行基准测试:BenchmarkTools.jl 包提供了更准确和可靠的基准测试工具:
    julia> using Cuba, BenchmarkTools
    
    julia> @time cuhre((x,f)->f[1]=x[1]*x[2]*x[3],3,1);
      0.055585 seconds (105.25 k allocations: 5.375 MiB)
    
    julia> @btime cuhre((x,f)->f[1]=x[1]*x[2]*x[3],3,1);
      37.067 μs (1527 allocations: 71.72 KiB)
    
    这比你想的要少几个数量级;
  2. @time@btime 宏都测量 Julia 端的内存分配,而不是可能调用的 C 库的内存分配,因此您看到的内存分配并非来自古巴图书馆;
  3. 你说内存分配加起来,但这不完全正确:因为每次调用集成函数分配的内存最终都会被释放。

如果 Cuba.jl is really an issue for you in practice (it rarely is for me), I strongly recommend you looking into the HCubature.jl package: it is written entirely in Julia, implements the same algorithm as cuhre from Cuba.jl and allows you to use StaticArrays.jlcuhre 的性能,在处理小尺寸(少于 ~16 个元素)时比标准数组更节省内存。