我尝试了以下代码,但代码之间的性能差异很大.我听说顶级代码不适合数值计算,但性能似乎也取决于顶级变量(此处为N)是否出现在for循环的范围内.避免这种顶级变量总是更好吗?
N = 10000000
# case1 (slow)
x = 0.0
@time for k = 1:N
x += float( k )
end
# case2 (slow)
@time let
y = 0.0
for j = 1:N
y += float( j )
end
end
# case3 (very fast)
@time let
n::Int64
n = N
z = 0.0
for m = 1:n
z += float( m )
end
end
# case 4 (slow)
function func1()
c = 0.0
for i = 1:N
c += float( …Run Code Online (Sandbox Code Playgroud) 有了x = Any[[1,2],[2,3],[3,4],[4,5]],我用Julia0.4.0尝试了以下这一行
x[ x .== [3,4] ]
Run Code Online (Sandbox Code Playgroud)
但它导致了一个错误
ERROR: DimensionMismatch("arrays could not be broadcast to a common size")
Run Code Online (Sandbox Code Playgroud)
我预期看到这样的信息Any[ [3,4] ],因为
x[3] == [3,4] # => true
Run Code Online (Sandbox Code Playgroud)
没问题.虽然此操作本身可能没用,但我想知道错误消息的含义.所以我很感激为什么会出现这个错误的提示.
我正在尝试创建包含不同类型变量的异构数组,例如[ 1.0, 7, "hi" ].我试图包含class(*)或type(*)在数组构造函数中(请参阅下面代码的结尾),但gfortran5.2只是将其视为语法错误.有没有办法用数组构造函数创建这样的数组,还是有必要使用不同的方法(例如,定义一个单独包含每个元素的类型)?
更多细节:
以下代码是我想创建这样一个数组的一个例子.该checktype_multi例程接收多个参数与所述optional关键字,但由于固定数量的参数的这种方法显然是有限的.为了允许任意数量的参数,我尝试了checktype_array例程,但似乎不可能传递具有不同类型的数组......更实际的情况可能是创建一个子例程来打印具有各种类型的可变数量的参数.
module mymod
implicit none
contains
subroutine checktype ( x )
class(*) :: x
select type ( x )
type is ( integer ) ; print *, "int : ", x
type is ( real ) ; print *, "real : ", x
type is ( character(*) ) ; print *, "string : ", x
endselect
end subroutine
subroutine checktype_multi …Run Code Online (Sandbox Code Playgroud) 在以下代码中,DO 循环的上限在循环内修改为
integer :: i1, i2, n1, n2
n1 = 4 ; n2 = 1
do i1 = 1, n1
do i2 = 1, n2
print *, "i1 =", i1, "i2 =", i2
n1 = 2
n2 = 2
enddo
enddo
Run Code Online (Sandbox Code Playgroud)
其中 gfortran4.8 和 ifort14.0 给出以下结果:
i1 = 1 i2 = 1
i1 = 2 i2 = 1
i1 = 2 i2 = 2
i1 = 3 i2 = 1
i1 = 3 i2 = 2
i1 = 4 i2 …Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我们将两个数组传递给子例程,并在DO循环中执行一些额外的操作.在这里,我们考虑三种不同操作的情况:情况1 =无操作,情况2和3 =指针变量的分配.
!------------------------------------------------------------------------
module mymod
implicit none
integer, pointer :: n_mod
integer :: nloop
contains
!.........................................................
subroutine test_2dim ( a, b, n )
integer :: n
real :: a(n,n), b(n,n)
integer, pointer :: n_ptr
integer i1, i2, iloop
n_ptr => n_mod
do iloop = 1, nloop
do i2 = 1, n
do i1 = 1, n
b(i1,i2) = a(i1,i2) + b(i1,i2) + iloop
!(nothing here) !! Case 1 : gfort => 3.6 sec, ifort => 3.2 sec
! n_ptr …Run Code Online (Sandbox Code Playgroud) 我一直在用小程序学习Chapel,他们工作得很好.但随着程序变得越来越长,编译时间也变得越来越长.所以我找到了逐个编译多个文件的方法,但还没有成功.通过搜索互联网,我找到了这个和这个页面,后者说
所有这些增量编译功能都在Chapel编译器中使用新的--incremental标志启用,该标志将在Chapel 1.14.0版本中提供.
虽然我的计算机上的Chapel编译器接受此选项,但在编译仅包含过程的文件(即没有main())时,它似乎不会生成任何*.o(或*.a?).这是因为上述项目是实验性的......?在这种情况下,我们可以期望这个功能被包含在Chapel的某个未来版本中吗?
(或者,上面的"增量编译"这个词不是我对GCC这样的通常编译器的预期吗?)
我的环境:在Mac OSX 10.11.6上通过自制软件安装Chapel-1.14.0.
与其他语言不同,Chapel中似乎没有allocate或new语法在堆上分配数组,而是使用通常的"声明"类语法.例如,在下面的代码中,我"声明"了两个数组,A并B在一个基于正式(虚拟)参数的函数中:
proc test( n, D )
{
var A: [1..n] real; // local array
var B: [D] real; // local array
writeln( "A.domain = ", A.domain );
writeln( "B.domain = ", B.domain );
}
test( 3, {2..5} ); // request small arrays
test( 10**7, {-10**7..10**7} ); // request large arrays
Run Code Online (Sandbox Code Playgroud)
这给出了以下结果:
A.domain = {1..3}
B.domain = {2..5}
A.domain = {1..10000000}
B.domain = {-10000000..10000000}
Run Code Online (Sandbox Code Playgroud)
因为没有堆栈溢出(尽管大小很大B),可以假设上面的语法总是在堆上分配A并且B不管它们的大小如何?
此外,域变量的赋值(或重新赋值)似乎扮演了数组的分配(或重新分配)的角色.例如,以下代码按预期工作.在这种情况下,分配是否总是在堆上发生(再次)?
var …Run Code Online (Sandbox Code Playgroud) 使用writef(),我可以控制浮点数的输出精度,例如:
writef( "%20.15dr\n", 1.0 / 3.0 ); // 0.333333333333333
Run Code Online (Sandbox Code Playgroud)
但如果我writeln()方便使用,则输出的数字为6位数:
writeln( 1.0 / 3.0 ); // 0.333333
Run Code Online (Sandbox Code Playgroud)
是否有可能控制浮点数的默认输出精度为writeln()...?(例如,通过一些环境变量?)
为了比较,默认情况下,某些语言输出15位数字和6位数字,因此结果似乎因语言(或编译器)而异.
# python2
print 1.0 / 3.0 # 0.333333333333
# python3
print( 1.0 / 3.0 ) # 0.3333333333333333
# julia
println( 1.0 / 3.0 ) # 0.3333333333333333
# gfortran
print *, 1.0d0 / 3.0d0 # 0.33333333333333331
# swift
print( 1.0 / 3.0 ) # 0.333333333333333
# nim
echo( 1.0 / 3.0 ) # 0.3333333333333333
# g++ …Run Code Online (Sandbox Code Playgroud) 在 Fortran 中,我总是使用双精度,因此我一直使用特定的函数,例如dble和dimag来获取复数变量的实部和虚部。但是,对于其他函数,例如sin,我不再使用dsin,因为前者返回正确类型的值(即,sin是通用函数)。对于复杂变量来说似乎也是如此。所以我的问题是:
1)最推荐的获取实部和虚部的通用函数是什么?
-- 似乎real(z)、aimag(z)、 和conjg(z)总是返回正确的类型(通过 gfortran 的实验),即,如果z是双精度,则这些函数返回双精度。这有保证吗?另外,行为是否取决于编译器使用的标准?(即 Fortran 77 与 90 或更高版本,特别是对于real(z)?)
2)如果我(尽管如此)想使用仅接收双精度参数并始终返回双精度值的特定函数,那么特定函数是什么?
-- 我一直在使用dble(z)和dreal(z), dimag(z),dconjg(z)--到目前为止,
我已经阅读了各个页面,但信息相当混乱(即,不太清楚什么是“标准”方式),所以我将不胜感激有关选择此类功能的任何建议。
在下面的代码中,我试图分配一个大小为0的空数组,然后使用自动重新分配添加更多元素:
integer, allocatable :: a(:)
allocate( a(0) ) ! Line 1
print *, size( a )
print *, "a(:) = ", a
a = [ a, 1 ]
print *, "a(:) = ", a
a = [ a, 2 ]
print *, "a(:) = ", a
!! Error
! a = []
! a = [ integer :: ]
Run Code Online (Sandbox Code Playgroud)
此代码给出了预期的结果(例如,使用gfortran或ifort -assume realloc_lhs)
0
a(:) =
a(:) = 1
a(:) = 1 2
Run Code Online (Sandbox Code Playgroud)
这里有三个问题:
allocate( a( 0 ) )? …我在Julia 0.4-prerelease中尝试以下代码,它以两种不同的方式执行矩阵求幂(精确vs系列扩展).我尝试使用几种方法来获取数组维度n和设置单位矩阵eye( n ).
function test()
A = [ 1.0 -1.0 ; -1.0 1.0 ]
lam, U = eig( A ) # diagonalization: A U = U diagm(lam)
Bref = U * diagm( exp(lam) ) * U' # Bref = exp(A) (in matrix sense)
#[ Get the dimension n ]
n = length( lam ) # slow (1a)
# const n = length( lam ) # slow (1b)
# n::Int = length( lam ) # fast …Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我将一个空数组传递给内部函数sum()和product()函数.
program test
implicit none
integer, allocatable :: A(:)
allocate( A( 0 ) )
print *, "sum = ", sum( A )
print *, "product = ", product( A )
end
Run Code Online (Sandbox Code Playgroud)
然后,我尝试过的所有编译器给出了相同的结果:
sum = 0
product = 1
Run Code Online (Sandbox Code Playgroud)
所以我想知道(1)是否允许将空数组传递给那些函数,以及(2)如果是这样,结果保证为0和1(根据Fortran标准).为了比较,一些其他语言(例如Python3)也给出0和1,其中(我猜)可能与极限sum( [1,2,...,n] )和product( [1,2,...,n] )to有关n -> 0.
>>> import numpy as np
>>> np.sum( [] )
0.0
>>> np.prod( [] )
1.0
Run Code Online (Sandbox Code Playgroud) 在我的代码中,我使用带有前导下划线的函数名称,例如_foo()出于某些目的,但想知道这是否可能产生副作用,例如,干扰从基本库导出的函数。例如,我看到类似的错误消息
ERROR: LoadError: ...
Stacktrace:
[1] _printf(::String, ::Expr, ::String, ::Tuple{Symbol,Expr,Symbol,Expr}) at ./printf.jl:1209
...
[7] _start() at ./client.jl:432
Run Code Online (Sandbox Code Playgroud)
虽然我猜这些是库中的内部函数(未导出),但对用户定义的函数使用这样的前导下划线是否安全(至少在仅使用标准库时)?