perf: implement paderborn suggestions

reduces memory consumption by removing unnecessary threading, references and utilising a different loop structure.

[skip ci]
This commit is contained in:
nebmit 2024-01-09 18:21:55 +01:00
parent d27917781c
commit bd01c0ee74
No known key found for this signature in database
3 changed files with 97 additions and 110 deletions

View File

@ -28,28 +28,20 @@ function calcBoundaryCoeff(
end end
function createCoeffMatrix( function createCoeffMatrix(
alpha::Matrix{T}, alpha::SubArray{T},
alpha_left::Vector{T}, alpha_left::SubArray{T},
alpha_right::Vector{T}, alpha_right::SubArray{T},
bcLeft::Vector{BoundaryElement{T}}, bcLeft::Vector{BoundaryElement{T}},
bcRight::Vector{BoundaryElement{T}}, bcRight::Vector{BoundaryElement{T}},
numCols::Int, numCols::Int,
rowIndex::Int, rowIndex::Int,
sx::T, sx::T,
)::Tridiagonal{T} where {T} )::Tridiagonal{T} where {T}
centerCoeffTop, rightCoeffTop = calcBoundaryCoeff( centerCoeffTop, rightCoeffTop =
alpha[rowIndex, 1], calcBoundaryCoeff(alpha[1], alpha[2], sx, getType(bcLeft[rowIndex]))
alpha[rowIndex, 2],
sx,
getType(bcLeft[rowIndex]),
)
centerCoeffBottom, leftCoeffBottom = calcBoundaryCoeff( centerCoeffBottom, leftCoeffBottom =
alpha[rowIndex, numCols], calcBoundaryCoeff(alpha[numCols], alpha[numCols-1], sx, getType(bcRight[rowIndex]))
alpha[rowIndex, numCols-1],
sx,
getType(bcRight[rowIndex]),
)
dl = [-sx .* alpha_left; leftCoeffBottom] dl = [-sx .* alpha_left; leftCoeffBottom]
d = [centerCoeffTop; 1 .+ sx .* (alpha_right + alpha_left); centerCoeffBottom] d = [centerCoeffTop; 1 .+ sx .* (alpha_right + alpha_left); centerCoeffBottom]
@ -95,25 +87,24 @@ end
function writeSolutionVector!( function writeSolutionVector!(
sv::Vector{T}, sv::Vector{T},
concentrations::Matrix{T}, concentrations_t::Matrix{T},
alphaX::Matrix{T}, alphaX::Matrix{T},
alphaY::Matrix{T}, alphaY::Matrix{T},
bcLeft::Vector{BoundaryElement{T}}, bcLeft::BoundaryElement{T},
bcRight::Vector{BoundaryElement{T}}, bcRight::BoundaryElement{T},
bcTop::Vector{BoundaryElement{T}}, bcTop::Vector{BoundaryElement{T}},
bcBottom::Vector{BoundaryElement{T}}, bcBottom::Vector{BoundaryElement{T}},
rowIndex::Int, rowIndex::Int,
sx::T, sx::T,
sy::T, sy::T,
) where {T} ) where {T}
numRows = size(concentrations, 1) numRows = size(concentrations_t, 2)
length = size(sv, 1)
if rowIndex == 1 if rowIndex == 1
@inbounds for i = 1:length @inbounds for i in eachindex(sv)
if getType(bcTop[i]) == CONSTANT if getType(bcTop[i]) == CONSTANT
sv[i] = calcExplicitConcentrationsBoundaryConstant( sv[i] = calcExplicitConcentrationsBoundaryConstant(
concentrations[rowIndex, i], concentrations_t[i, rowIndex],
getValue(bcTop[i]), getValue(bcTop[i]),
alphaY[rowIndex, i], alphaY[rowIndex, i],
alphaY[rowIndex+1, i], alphaY[rowIndex+1, i],
@ -121,7 +112,7 @@ function writeSolutionVector!(
) )
elseif getType(bcTop[i]) == CLOSED elseif getType(bcTop[i]) == CLOSED
sv[i] = calcExplicitConcentrationsBoundaryClosed( sv[i] = calcExplicitConcentrationsBoundaryClosed(
concentrations[rowIndex, i], concentrations_t[i, rowIndex],
alphaY[rowIndex, i], alphaY[rowIndex, i],
alphaY[rowIndex+1, i], alphaY[rowIndex+1, i],
sy, sy,
@ -133,25 +124,26 @@ function writeSolutionVector!(
end end
if rowIndex > 1 && rowIndex < numRows if rowIndex > 1 && rowIndex < numRows
@inbounds for i = 1:length @inbounds for i in eachindex(sv)
alpha_here_below = alpha_here_below =
calcAlphaIntercell(alphaY[rowIndex, i], alphaY[rowIndex+1, i]) calcAlphaIntercell(alphaY[rowIndex, i], alphaY[rowIndex+1, i])
alpha_here_above = alpha_here_above =
alphaY[rowIndex+1, i] == alphaY[rowIndex-1, i] ? alpha_here_below : alphaY[rowIndex+1, i] == alphaY[rowIndex-1, i] ? alpha_here_below :
calcAlphaIntercell(alphaY[rowIndex-1, i], alphaY[rowIndex, i]) calcAlphaIntercell(alphaY[rowIndex-1, i], alphaY[rowIndex, i])
sv[i] = sv[i] =
sy * alpha_here_below * concentrations[rowIndex+1, i] + sy * alpha_here_below * concentrations_t[i, rowIndex+1] +
(1 - sy * (alpha_here_below + alpha_here_above)) * (1 - sy * (alpha_here_below + alpha_here_above)) *
concentrations[rowIndex, i] + concentrations_t[i, rowIndex] +
sy * alpha_here_above * concentrations[rowIndex-1, i] sy * alpha_here_above * concentrations_t[i, rowIndex-1]
end end
end end
if rowIndex == numRows if rowIndex == numRows
@inbounds for i = 1:length @inbounds for i in eachindex(sv)
if getType(bcBottom[i]) == CONSTANT if getType(bcBottom[i]) == CONSTANT
sv[i] = calcExplicitConcentrationsBoundaryConstant( sv[i] = calcExplicitConcentrationsBoundaryConstant(
concentrations[rowIndex, i], concentrations_t[i, rowIndex],
getValue(bcBottom[i]), getValue(bcBottom[i]),
alphaY[rowIndex, i], alphaY[rowIndex, i],
alphaY[rowIndex-1, i], alphaY[rowIndex-1, i],
@ -159,7 +151,7 @@ function writeSolutionVector!(
) )
elseif getType(bcBottom[i]) == CLOSED elseif getType(bcBottom[i]) == CLOSED
sv[i] = calcExplicitConcentrationsBoundaryClosed( sv[i] = calcExplicitConcentrationsBoundaryClosed(
concentrations[rowIndex, i], concentrations_t[i, rowIndex],
alphaY[rowIndex, i], alphaY[rowIndex, i],
alphaY[rowIndex-1, i], alphaY[rowIndex-1, i],
sy, sy,
@ -170,12 +162,12 @@ function writeSolutionVector!(
end end
end end
if getType(bcLeft[rowIndex]) == CONSTANT if getType(bcLeft) == CONSTANT
sv[1] += 2 * sx * alphaX[rowIndex, 1] * getValue(bcLeft[rowIndex]) sv[1] += 2 * sx * alphaX[rowIndex, 1] * getValue(bcLeft)
end end
if getType(bcRight[rowIndex]) == CONSTANT if getType(bcRight) == CONSTANT
sv[end] += 2 * sx * alphaX[rowIndex, end] * getValue(bcRight[rowIndex]) sv[end] += 2 * sx * alphaX[rowIndex, end] * getValue(bcRight)
end end
end end
@ -196,9 +188,9 @@ function BTCS_1D(
concentrations::Matrix{T} = getConcentrations(grid) concentrations::Matrix{T} = getConcentrations(grid)
A::Tridiagonal{T} = createCoeffMatrix( A::Tridiagonal{T} = createCoeffMatrix(
alpha, view(alpha, 1, :),
alpha_left[1, :], view(alpha_left, 1, :),
alpha_right[1, :], view(alpha_right, 1, :),
bcLeft, bcLeft,
bcRight, bcRight,
length, length,
@ -239,20 +231,19 @@ function BTCS_2D(
concentrations = getConcentrations(grid) concentrations = getConcentrations(grid)
concentrations_intermediate = similar(concentrations) concentrations_intermediate = similar(concentrations)
concentrations_t_task = Threads.@spawn copy(transpose(concentrations)) concentrations_t = copy(transpose(concentrations))
bcLeft = getBoundarySide(bc, LEFT) bcLeft = getBoundarySide(bc, LEFT)
bcRight = getBoundarySide(bc, RIGHT) bcRight = getBoundarySide(bc, RIGHT)
bcTop = getBoundarySide(bc, TOP) bcTop = getBoundarySide(bc, TOP)
bcBottom = getBoundarySide(bc, BOTTOM) bcBottom = getBoundarySide(bc, BOTTOM)
localBs = [zeros(T, cols) for _ = 1:Threads.nthreads()]
Threads.@threads for i = 1:rows Threads.@threads for i = 1:rows
localB = localBs[Threads.threadid()] localB = zeros(T, cols)
A::Tridiagonal{T} = createCoeffMatrix( A::Tridiagonal{T} = createCoeffMatrix(
alphaX, view(alphaX, i, :),
alphaX_left[i, :], view(alphaX_left, i, :),
alphaX_right[i, :], view(alphaX_right, i, :),
bcLeft, bcLeft,
bcRight, bcRight,
cols, cols,
@ -261,11 +252,11 @@ function BTCS_2D(
) )
writeSolutionVector!( writeSolutionVector!(
localB, localB,
concentrations, concentrations_t,
alphaX, alphaX,
alphaY, alphaY,
bcLeft, bcLeft[i],
bcRight, bcRight[i],
bcTop, bcTop,
bcBottom, bcBottom,
i, i,
@ -276,17 +267,13 @@ function BTCS_2D(
concentrations_intermediate[i, :] = A \ localB concentrations_intermediate[i, :] = A \ localB
end end
concentrations_intermediate = copy(transpose(concentrations_intermediate))
concentrations_t = fetch(concentrations_t_task)
# Swap alphas, boundary conditions and sx/sy for column-wise calculation # Swap alphas, boundary conditions and sx/sy for column-wise calculation
localBs = [zeros(T, rows) for _ = 1:Threads.nthreads()]
Threads.@threads for i = 1:cols Threads.@threads for i = 1:cols
localB = localBs[Threads.threadid()] localB = zeros(T, cols)
A::Tridiagonal{T} = createCoeffMatrix( A::Tridiagonal{T} = createCoeffMatrix(
alphaY_t, view(alphaY_t, i, :),
alphaY_t_left[i, :], view(alphaY_t_left, i, :),
alphaY_t_right[i, :], view(alphaY_t_right, i, :),
bcTop, bcTop,
bcBottom, bcBottom,
rows, rows,
@ -298,8 +285,8 @@ function BTCS_2D(
concentrations_intermediate, concentrations_intermediate,
alphaY_t, alphaY_t,
alphaX_t, alphaX_t,
bcTop, bcTop[i],
bcBottom, bcBottom[i],
bcLeft, bcLeft,
bcRight, bcRight,
i, i,

View File

@ -127,8 +127,8 @@ function FTCS_1D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
colMax = getCols(grid) colMax = getCols(grid)
sx = timestep / (getDeltaCol(grid)^2) sx = timestep / (getDeltaCol(grid)^2)
concentrations = getConcentrations(grid)
alphaX = getAlphaX(grid) alphaX = getAlphaX(grid)
concentrations = getConcentrations(grid)
concentrations_t1 = copy(concentrations) concentrations_t1 = copy(concentrations)
row = 1 row = 1
@ -184,26 +184,6 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
concentrations_t1 = copy(concentrations) concentrations_t1 = copy(concentrations)
Threads.@threads for row = 2:rowMax-1 Threads.@threads for row = 2:rowMax-1
for col = 2:colMax-1
concentrations_t1[row, col] +=
sy * calcVerticalChange(
alphaY[row+1, col],
alphaY[row-1, col],
alphaY[row, col],
concentrations[row+1, col],
concentrations[row-1, col],
concentrations[row, col],
) +
sx * calcHorizontalChange(
alphaX[row, col+1],
alphaX[row, col-1],
alphaX[row, col],
concentrations[row, col+1],
concentrations[row, col-1],
concentrations[row, col],
)
end
concentrations_t1[row, 1] += concentrations_t1[row, 1] +=
sx * calcHorizontalChangeLeftBoundary( sx * calcHorizontalChangeLeftBoundary(
getBoundaryElementType(bc, LEFT, row), getBoundaryElementType(bc, LEFT, row),
@ -242,6 +222,26 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
end end
Threads.@threads for col = 2:colMax-1 Threads.@threads for col = 2:colMax-1
for row = 2:rowMax-1
concentrations_t1[row, col] +=
sy * calcVerticalChange(
alphaY[row+1, col],
alphaY[row-1, col],
alphaY[row, col],
concentrations[row+1, col],
concentrations[row-1, col],
concentrations[row, col],
) +
sx * calcHorizontalChange(
alphaX[row, col+1],
alphaX[row, col-1],
alphaX[row, col],
concentrations[row, col+1],
concentrations[row, col-1],
concentrations[row, col],
)
end
concentrations_t1[1, col] += concentrations_t1[1, col] +=
sy * calcVerticalChangeTopBoundary( sy * calcVerticalChangeTopBoundary(
getBoundaryElementType(bc, TOP, col), getBoundaryElementType(bc, TOP, col),

View File

@ -35,11 +35,11 @@ struct Grid{T}
domainRow::T domainRow::T
deltaCol::T deltaCol::T
deltaRow::T deltaRow::T
concentrations::Ref{Matrix{T}} concentrations::Matrix{T}
alphaX::Ref{Matrix{T}} alphaX::Matrix{T}
alphaY::Union{Ref{Matrix{T}},Nothing} alphaY::Union{Matrix{T},Nothing}
alphaX_t::Union{Ref{Matrix{T}},Nothing} alphaX_t::Matrix{T}
alphaY_t::Union{Ref{Matrix{T}},Nothing} alphaY_t::Union{Matrix{T},Nothing}
function Grid{T}(length::Int, alphaX::Matrix{T})::Grid{T} where {T} function Grid{T}(length::Int, alphaX::Matrix{T})::Grid{T} where {T}
if length <= 3 if length <= 3
@ -63,7 +63,7 @@ struct Grid{T}
0, 0,
T(1), T(1),
0, 0,
Ref(fill(T(0), 1, length)), fill(T(0), 1, length),
alphaX, alphaX,
nothing, nothing,
alphaX_t, alphaX_t,
@ -103,7 +103,7 @@ struct Grid{T}
T(rows), T(rows),
T(1), T(1),
T(1), T(1),
Ref(fill(T(0), rows, cols)), fill(T(0), rows, cols),
alphaX, alphaX,
alphaY, alphaY,
alphaX_t, alphaX_t,
@ -119,11 +119,11 @@ struct Grid{T}
domainRow::T, domainRow::T,
deltaCol::T, deltaCol::T,
deltaRow::T, deltaRow::T,
concentrations::Ref{Matrix{T}}, concentrations::Matrix{T},
alphaX::Ref{Matrix{T}}, alphaX::Matrix{T},
alphaY::Union{Ref{Matrix{T}},Nothing}, alphaY::Union{Matrix{T},Nothing},
alphaX_t::Union{Ref{Matrix{T}},Nothing}, alphaX_t::Matrix{T},
alphaY_t::Union{Ref{Matrix{T}},Nothing}, alphaY_t::Union{Matrix{T},Nothing},
)::Grid{T} where {T} )::Grid{T} where {T}
new{T}( new{T}(
cols, cols,
@ -164,10 +164,10 @@ function clone(grid::Grid{T})::Grid{T} where {T}
grid.domainRow, grid.domainRow,
grid.deltaCol, grid.deltaCol,
grid.deltaRow, grid.deltaRow,
Ref(copy(grid.concentrations[])), copy(grid.concentrations),
Ref(copy(grid.alphaX[])), copy(grid.alphaX),
nothing, nothing,
Ref(copy(grid.alphaX_t[])), copy(grid.alphaX_t),
nothing, nothing,
) )
end end
@ -179,11 +179,11 @@ function clone(grid::Grid{T})::Grid{T} where {T}
grid.domainRow, grid.domainRow,
grid.deltaCol, grid.deltaCol,
grid.deltaRow, grid.deltaRow,
Ref(copy(grid.concentrations[])), copy(grid.concentrations),
Ref(copy(grid.alphaX[])), copy(grid.alphaX),
Ref(copy(grid.alphaY[])), copy(grid.alphaY),
Ref(copy(grid.alphaX_t[])), copy(grid.alphaX_t),
Ref(copy(grid.alphaY_t[])), copy(grid.alphaY_t),
) )
end end
@ -199,7 +199,7 @@ Retrieves the alpha coefficients matrix in the X direction from the specified gr
The `alphaX` matrix of the grid. The `alphaX` matrix of the grid.
""" """
function getAlphaX(grid::Grid{T})::Matrix{T} where {T} function getAlphaX(grid::Grid{T})::Matrix{T} where {T}
grid.alphaX[] grid.alphaX
end end
""" """
@ -219,7 +219,7 @@ function getAlphaY(grid::Grid{T})::Matrix{T} where {T}
error("Grid is 1D, so there is no alphaY matrix!") error("Grid is 1D, so there is no alphaY matrix!")
end end
grid.alphaY[] grid.alphaY
end end
""" """
@ -234,7 +234,7 @@ Retrieves the transposed alpha coefficients matrix in the X direction from the s
The transposed `alphaX_t` matrix of the grid. The transposed `alphaX_t` matrix of the grid.
""" """
function getAlphaX_t(grid::Grid{T})::Matrix{T} where {T} function getAlphaX_t(grid::Grid{T})::Matrix{T} where {T}
grid.alphaX_t[] grid.alphaX_t
end end
""" """
@ -254,7 +254,7 @@ function getAlphaY_t(grid::Grid{T})::Matrix{T} where {T}
error("Grid is 1D, so there is no alphaY_t matrix!") error("Grid is 1D, so there is no alphaY_t matrix!")
end end
grid.alphaY_t[] grid.alphaY_t
end end
""" """
@ -284,7 +284,7 @@ Retrieves the concentration matrix from the specified grid.
The concentration matrix of the grid. The concentration matrix of the grid.
""" """
function getConcentrations(grid::Grid{T})::Matrix{T} where {T} function getConcentrations(grid::Grid{T})::Matrix{T} where {T}
grid.concentrations[] grid.concentrations
end end
""" """
@ -361,7 +361,7 @@ Throws an error if the dimensions of the new matrix don't match the grid's dimen
Nothing, but modifies the alphaX matrix of the grid. Nothing, but modifies the alphaX matrix of the grid.
""" """
function setAlphaX!(grid::Grid{T}, new_alphaX::Matrix{T})::Nothing where {T} function setAlphaX!(grid::Grid{T}, new_alphaX::Matrix{T})::Nothing where {T}
if size(new_alphaX) != size(grid.alphaX[]) if size(new_alphaX) != size(grid.alphaX)
throw( throw(
ArgumentError( ArgumentError(
"Given matrix of alpha coefficients mismatch with Grid dimensions!", "Given matrix of alpha coefficients mismatch with Grid dimensions!",
@ -369,8 +369,8 @@ function setAlphaX!(grid::Grid{T}, new_alphaX::Matrix{T})::Nothing where {T}
) )
end end
grid.alphaX[] = new_alphaX grid.alphaX .= new_alphaX
grid.alphaX_t[] = new_alphaX' grid.alphaX_t .= new_alphaX'
return return
end end
@ -391,7 +391,7 @@ function setAlphaY!(grid::Grid{T}, new_alphaY::Matrix{T})::Nothing where {T}
if grid.dim == 1 if grid.dim == 1
error("Grid is 1D, so there is no alphaY matrix!") error("Grid is 1D, so there is no alphaY matrix!")
end end
if size(new_alphaY) != size(grid.alphaY[]) if size(new_alphaY) != size(grid.alphaY)
throw( throw(
ArgumentError( ArgumentError(
"Given matrix of alpha coefficients mismatch with Grid dimensions!", "Given matrix of alpha coefficients mismatch with Grid dimensions!",
@ -399,8 +399,8 @@ function setAlphaY!(grid::Grid{T}, new_alphaY::Matrix{T})::Nothing where {T}
) )
end end
grid.alphaY[] = new_alphaY grid.alphaY .= new_alphaY
grid.alphaY_t[] = new_alphaY' grid.alphaY_t .= new_alphaY'
return return
end end
@ -418,12 +418,12 @@ Throws an error if the dimensions of the new matrix don't match the grid's dimen
Nothing, but modifies the concentration matrix of the grid. Nothing, but modifies the concentration matrix of the grid.
""" """
function setConcentrations!(grid::Grid{T}, new_concentrations::Matrix{T})::Nothing where {T} function setConcentrations!(grid::Grid{T}, new_concentrations::Matrix{T})::Nothing where {T}
if size(new_concentrations) != size(grid.concentrations[]) if size(new_concentrations) != size(grid.concentrations)
throw( throw(
ArgumentError("Given matrix of concentrations mismatch with Grid dimensions!"), ArgumentError("Given matrix of concentrations mismatch with Grid dimensions!"),
) )
end end
grid.concentrations[] = new_concentrations grid.concentrations .= new_concentrations
return return
end end