如何在Julia中将对象数组传递给函数?

4

我想将一个对象数组传递给函数,并返回另一个相同大小的数组。应该如何实现?代码应该非常快。例如,考虑以下代码:

struct triangle
    height::Float64
    base::Float64
end

function area(height::Float64, base::Float64)
    return 0.5*base*height
end

我想定义一个函数,用于返回一个三角形数组的面积。最快的方法是什么?

2个回答

10
您可以利用Julia的广播语法来实现此功能。请考虑以下示例:
struct Triangle # Note: Julia convention is to capitalize types
    height::Float64
    base::Float64
end

# Define an area method for the Triangle type
area(t::Triangle) = 0.5 * t.height * t.base

# Create an area of random triangles
triangle_array = [Triangle(rand(), rand()) for _ in 1:10]

# Now we can use dot syntax to broadcast our area function over the array of triangles
area.(triangle_array)

请注意,这与您的代码不同,它直接使用Triangle对象进行调度,用于调用area函数。然后,area函数不再需要heightbase参数,而只需要一个单独的Triangle对象,以及访问其heightbase属性(t.heightt.base)。

1
通常情况下,最好使用除以2(一个Int)而不是乘以0.5(一个Float64)进行除法。考虑heightbase为例如Float32的情况,前者将得到一个Float32,而后者将不必要地提升为Float64。因此,我会这样写:area(t::Triangle) = t.height * t.base / 2 - fredrikekre

4

以下是使用以下方式计算这个值的一些基准测试:

  • 映射: map(area, triangles)
  • 列表推导式: `[area(triangle) for triangle in triangles]
  • 广播: area.(triangles)

使用插值符号$对非本地全局变量triangles进行插值(基于 @DNF 评论)。

定义

using Pkg
Pkg.add("BenchmarkTools")
using BenchmarkTools


struct Triangle
    height::Float64
    base::Float64
end


function area(t::Triangle)
    0.5 * t.height * t.base
end


triangles = [Triangle(rand(), rand()) for _ in 1:1000000]

结果

julia> @benchmark map(area, $triangles)
BenchmarkTools.Trial: 
  memory estimate:  7.63 MiB
  allocs estimate:  3
  --------------
  minimum time:     1.168 ms (0.00% GC)
  median time:      2.510 ms (0.00% GC)
  mean time:        2.485 ms (10.00% GC)
  maximum time:     43.540 ms (91.62% GC)
  --------------
  samples:          2008
  evals/sample:     1

julia> @benchmark [area(triangle) for triangle in $triangles]
BenchmarkTools.Trial: 
  memory estimate:  7.63 MiB
  allocs estimate:  3
  --------------
  minimum time:     1.150 ms (0.00% GC)
  median time:      1.921 ms (0.00% GC)
  mean time:        2.327 ms (10.76% GC)
  maximum time:     45.883 ms (91.42% GC)
  --------------
  samples:          2144
  evals/sample:     1

julia> @benchmark area.($triangles)
BenchmarkTools.Trial: 
  memory estimate:  7.63 MiB
  allocs estimate:  2
  --------------
  minimum time:     1.165 ms (0.00% GC)
  median time:      1.224 ms (0.00% GC)
  mean time:        1.961 ms (10.13% GC)
  maximum time:     44.156 ms (89.33% GC)
  --------------
  samples:          2544
  evals/sample:     1

这表明对于此输入大小,广播方法似乎是最快的。

对于不同的输入大小,相对时间可能会有所不同,因此为您的用例自行进行基准测试可能是个好主意。


3
在使用BenchmarkTools.jl进行基准测试时,始终记得插值全局非常量变量。如果我在上面的代码中将triangles替换为$triangles,则三个方案的运行时间相似,此时我会因其语法而更喜欢广播。 - DNF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接