Octave并行包:用户自定义函数调用问题

Octave parallel package: User-defined function call issues

我无法使用 pararrayfun 调用用户定义的函数(对于 parcellfun 也是如此)。当我执行以下代码时:

pkg load parallel

function retval = mul(x,y)
  retval = x*y;
endfunction

vector_x = 1:2^3;
vector_y = 1:2^3;

vector_z = pararrayfun(nproc, @(x,y) mul(x,y), vector_x, vector_y)
vector_z = pararrayfun(nproc, @(x,y) x*y, vector_x, vector_y)

我得到以下输出:

vector_z =

  -1  -1  -1  -1  -1  -1  -1  -1

vector_z =

    1    4    9   16   25   36   49   64

也就是说,调用用户自定义函数似乎不起作用,而像匿名函数一样起作用。

机器 x86_64 装有 Debian bullseye 和 5.10.0-1-amd64 内核。 Octave的版本是6.1.1~hg.2020.12.27-1。 pkg list 命令给我:

Package Name  | Version | Installation directory
--------------+---------+-----------------------
   dataframe  |   1.2.0 | /usr/share/octave/packages/dataframe-1.2.0
    parallel *|   4.0.0 | /usr/share/octave/packages/parallel-4.0.0
      struct *|  1.0.16 | /usr/share/octave/packages/struct-1.0.16

有趣的是,相同的代码在带有 Debian buster 和 4.14.150-odroidxu4 内核的 armv7l 上可以完美运行。这是对用户定义函数的调用,匿名函数产生输出:

parcellfun: 8/8 jobs done
vector_z =

    1    4    9   16   25   36   49   64

parcellfun: 8/8 jobs done
vector_z =

    1    4    9   16   25   36   49   64

在那台机器上,Octave 的版本是 4.4.1,pkg list 给出:

Package Name  | Version | Installation directory
--------------+---------+-----------------------
   dataframe  |   1.2.0 | /usr/share/octave/packages/dataframe-1.2.0
    parallel *|   3.1.3 | /usr/share/octave/packages/parallel-3.1.3
      struct *|  1.0.15 | /usr/share/octave/packages/struct-1.0.15

出了什么问题,我该如何解决这个问题?

这可能是一个错误,但请注意,新版本的 parallel 根据其 documentation (also see the latest release news) 引入了一些限制,这可能与此处发生的事情有关。

说到这里,我想澄清一下这句话:

the call to the user-defined funtion does not seem to work, whereas the same as an anonymous function is working.

事实并非如此。在这两种情况下,您都传递了一个匿名函数。只是第一次在里面调用了mul,第二次调用了mtimes。

至于你的错误(错误?),这可能与 mul 是一个 'command-line' 函数有关。从文档中不清楚命令行功能是否是一个限制,这只是文档中的疏忽,或者对命令行功能的虐待是否是一个真正的错误。我想如果你把它放在自己的文件中它应该可以正常工作。 (同样,如果你这样做,值得直接将其作为句柄传递,而不是将其包装在另一个匿名函数中)。

话虽如此,我认为您看到的 -1 基本上是 pararrayfun 内部的“错误 returns”。原因如下:如果不是将 mul 创建为命令行函数,而是将其设为匿名函数:

mul = @(x,y) x * y

观察下面三个调用的内容return:

x = pararrayfun( nproc, @(x,y) mul(x,y), vector_x, vector_y )   # now it works as expected.
x = pararrayfun( nproc, mul, vector_x, vector_y )   # same: mul is a valid handle expecting two inputs
x = pararrayfun( nproc, @mul, vector_x, vector_y )  # x=-1,-1,-1,-1,-1,-1,-1,-1

如果您尝试过使用普通数组 fun 的最后一个命令,您会看到一个错误,该错误与您不小心传递了 @mul 而不是 mul 相关,而 mul 是一个正确的句柄。在 pararrayfun 中,它只是进行计算,并且大概 -1 是来自内部错误的 return 值。

我不知道为什么命令行函数会失败,但大概与 pararrayfun 在后台创建单独的八度实例有关,它需要访问所有函数定义,也许还有命令-line 函数不能像在父实例中那样容易地在新实例中传输/编译,因为它们在当前会话中创建/编译的方式。

无论如何,我认为如果您创建一个外部函数或(如果处理的函数足够简单)一个匿名函数的句柄而不是命令行函数定义,您将解决您的问题。

但是,我仍然会向 octave bug tracker 提交错误以帮助项目:)