Random 我们能用Fortran语言创建生成随机数的纯函数吗?
我的目标是使用随机数编写一个纯函数,它可以用于DO并发结构。编译器似乎不允许这样做Random 我们能用Fortran语言创建生成随机数的纯函数吗?,random,concurrency,fortran,gfortran,Random,Concurrency,Fortran,Gfortran,我的目标是使用随机数编写一个纯函数,它可以用于DO并发结构。编译器似乎不允许这样做 mwe.f95:8:30: call init_seed ( ) 1 Error: Subroutine call to ‘init_seed’ at (1) is not PURE mwe.f95:9:36: call random_number ( y )
mwe.f95:8:30:
call init_seed ( )
1
Error: Subroutine call to ‘init_seed’ at (1) is not PURE
mwe.f95:9:36:
call random_number ( y )
1
Error: Subroutine call to intrinsic ‘random_number’ at (1) is not PURE
mwe.f95:16:8:
use myFunction
1
Fatal Error: Can't open module file ‘myfunction.mod’ for reading at (1): No such file or directory
compilation terminated.
为什么会这样?有没有一种方法可以在纯例程中生成随机数
MWE如下所示。编译命令为gfortran mwe.f95
。编译器版本为GCC 5.1.0
module myFunction
implicit none
contains
pure real function action ( ) result ( new_number )
real :: y
call init_seed ( )
call random_number ( y )
new_number = y**2
end function
end module myFunction
program mwe
use myFunction
implicit none
real :: x
x = action ( )
end program mwe
这完全违背了纯粹的概念。在真正的函数语言中,真正的纯函数应该总是为相同的输入返回相同的结果。Fortran纯函数可以读取模块变量,因此更复杂 让任何函数(不仅仅是纯函数)返回伪随机数都不是一个好主意。当一个表达式中有更多函数调用时,Fortran编译器只允许对函数求值一次。当该函数是纯函数时,这种情况更有可能发生,或者说更合理
我建议只使用常规DO循环并调用
随机数
或其他自定义PRNG子例程。即使您想要自动并行化或类似的功能,编译器通常也能够将常规DO循环与并发DO循环同等对待。这完全违背了纯粹性的概念。在真正的函数语言中,真正的纯函数应该总是为相同的输入返回相同的结果。Fortran纯函数可以读取模块变量,因此更复杂
让任何函数(不仅仅是纯函数)返回伪随机数都不是一个好主意。当一个表达式中有更多函数调用时,Fortran编译器只允许对函数求值一次。当该函数是纯函数时,这种情况更有可能发生,或者说更合理
我建议只使用常规DO循环并调用
随机数
或其他自定义PRNG子例程。即使您需要自动并行或类似的功能,编译器通常也能够处理常规DO循环和并发DO循环。您需要纯随机数生成器。例如,对于线性同余生成器,种子(64位无符号整数)与状态相同,与返回值相同。在这种情况下,状态/种子保存在采样例程外部,显式传递,从RNG获取时存储您将需要纯随机数生成器。例如,对于线性同余生成器,种子(64位无符号整数)与状态相同,与返回值相同。在这种情况下,状态/种子保存在采样例程外部,显式传递,并在从RNG获取时存储据我所知,纯函数不会有副作用。调用PRNG API通常会产生副作用,即更新PRNG的内部状态:考虑在<代码>之前执行一个随机值数组,同时执行并发< /代码>构造,然后在并发循环中,您会遇到一些类似于<代码> x(i)=动作(RANDARAMEL(i))< /代码>,action
是一个合适的纯函数。如果我们理解您为什么希望在这种情况下使用纯函数,我们可能会为您提供最好的帮助(超出Vlad非常好的答案)。@agentp:谢谢。我对VF的评论是在我读这篇文章之前写的。还有一种可能性:使用SIMD而不是并发。但你可能需要引入一些结构性的变化。然后你可以用不纯元素代替纯过程。我知道,纯函数不会有副作用。调用PRNG API通常会产生副作用,即更新PRNG的内部状态:考虑在<代码>之前执行一个随机值数组,同时执行并发< /代码>构造,然后在并发循环中,您会遇到一些类似于<代码> x(i)=动作(RANDARAMEL(i))< /代码>,action
是一个合适的纯函数。如果我们理解您为什么希望在这种情况下使用纯函数,我们可能会为您提供最好的帮助(超出Vlad非常好的答案)。@agentp:谢谢。我对VF的评论是在我读这篇文章之前写的。还有一种可能性:使用SIMD而不是并发。但你可能需要引入一些结构性的变化。然后,您可以使用不纯元素而不是纯过程。我假设在do concurrent
上下文中,您需要为每个并发实例维护不同种子的向量。该函数必须返回一个包含生成的编号和新状态的派生类型,但是的,这是可能的。我还是更喜欢子程序。PRNG am using(不在do concurrent中)实际上接受这样的内容,但是在OpenMP和我必须注意保持每个线程的状态是分开的。@agentp在do concurrent
上下文中,不管RNG是纯的还是非纯的,您都必须维护种子/状态向量not@agentp:我们依赖于使用pid生成种子的标准技巧。我们还内置了一个选项,通过读取/dev/uradom使用系统中的种子。目前尚不清楚这是否适用于并发计算。欢迎评论。@dantopa这是我所说的RNG,它与MCNP5中的基本相同。它具有快速log2(N)提前跳过(aka discard)。如果将种子/状态设置为外部参数,您可以将代码转换为适用于concurrent
contextI的纯函数。我假设在do concurrent
上下文中,您需要为每个并发实例维护一个包含不同种子的向量。该函数必须返回一个包含生成的编号和新状态的派生类型,但是,这是可能的。我还是更喜欢子程序。PRNG am using(不在do concurrent中)实际上接受类似的内容,但在OpenMP和我必须注意保持每个线程的状态sepa