Octave parallel package:用户定义函数调用问题



我在使用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

有趣的是,同样的代码在armv7l和Debian buster和4.14.150-odroidxu4内核上完美地工作。这是对用户定义函数的调用,匿名函数产生输出:

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

什么是错误的,我如何解决这个行为?

这可能是一个bug,但请注意,新版本的parallel根据其文档(也请参阅最新发布新闻)引入了一些限制,这可能与这里发生的事情有关。

说了这些,我想澄清这句话:

对用户定义函数的调用似乎不工作,而与匿名函数相同的是工作。

事情不是这样的。在这两种情况下都传递了一个匿名函数。只是第一个在内部调用mul,第二个调用mtimes。

至于你的错误(bug?)这可能与mul是一个'命令行'函数有关。从文档中不清楚命令行函数是否是一个限制,这只是文档中的疏忽,或者命令行函数的滥用是否是一个真正的错误。我想如果你把它放到它自己的文件里,应该没问题。(同样,如果你这样做了,它值得作为句柄直接传递,而不是将它包装在另一个匿名函数中)。

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

mul = @(x,y) x * y

观察下面三个调用返回的结果:

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是内部错误的返回值。

我不知道命令行函数失败的确切原因,但可能与pararrayfun在底层创建单独的octave实例有关,这些实例需要访问所有函数定义,也许命令行函数不能像在父实例中那样容易地在新实例中转移/编译,因为它们是在当前会话中创建/编译的。

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

然而,我仍然会向octave bug跟踪器提交一个bug来帮助这个项目:)

最新更新