使用GSL计算矩阵Kronecker乘积的有效方法

我的算法的瓶颈是我的functionKronecker产品叫KPro:

gsl_matrix *KPro(gsl_matrix *a, gsl_matrix *b) { int i, j, k, l; int m, p, n, q; m = a->size1; p = a->size2; n = b->size1; q = b->size2; gsl_matrix *c = gsl_matrix_alloc(m*n, p*q); double da, db; for (i = 0; i < m; i++) { for (j = 0; j < p; j++) { da = gsl_matrix_get (a, i, j); for (k = 0; k < n; k++) { for (l = 0; l < q; l++) { db = gsl_matrix_get (b, k, l); gsl_matrix_set (c, n*i+k, q*j+l, da * db); } } } } return c; } 

您是否知道使用GSL的有效实施? 我找不到合适的例程。

只是表面上看,我可以在你的日常工作中看到很多可能的瓶颈:

  1. 重复使用矩阵c而不是每次重新分配它,即从函数堆栈变量升级到类成员或从静态升级到文件。 分配一次并尽可能地解决问题的大小。
  2. 调用所有这些gsl_matrix_get和gsl_matrix_set肯定会阻止编译器对代码进行自动向量化,而是考虑使用带有重载或内联运算符和直接内存访问的基于模板的矩阵实现。
  3. 想想你正在使用的矩阵排序:它是行主要吗? 或专栏? 缓存未命中比你在那里做的任何事情都要贵。 您希望利用空间局部性和重用,通过以最内层循环(计算发生的位置)访问已经预取的相邻矩阵元素的方式重新排序循环来实现。
  4. 对齐内存分配,使向量化更容易,更有效。
  5. 考虑使用循环展开和阻止

您可以通过“阻止”并更有效地利用缓存来显着提高性能。

看看这篇论文 。 是否有伪代码,我认为你将能够轻松地变成C代码。 它还有一个算法,可以根据高速缓存大小和矩阵参数确定最佳块大小。