Skip to content

Commit e4e8c19

Browse files
authored
Only @noinline error path in matmul_size_check (#1310)
Instead of `@noinline` on the entire size-check function, we now separate the error-throwing part into a separate function and mark it as `@noinline`. This way, the size check may still be evaluated inline, and only the error path will not be inlined. This improves performance for small matmul. ```julia julia> A = [1 2; 3 4]; julia> @Btime $A * $A; 53.361 ns (2 allocations: 112 bytes) # v"1.13.0-DEV.438" 47.504 ns (2 allocations: 112 bytes) # this PR ```
1 parent bfab205 commit e4e8c19

File tree

1 file changed

+42
-34
lines changed

1 file changed

+42
-34
lines changed

src/matmul.jl

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -412,52 +412,60 @@ lmul!(A, B)
412412

413413
_vec_or_mat_str(s::Tuple{Any}) = "vector"
414414
_vec_or_mat_str(s::Tuple{Any,Any}) = "matrix"
415-
@noinline function matmul_size_check(sizeA::Tuple{Integer,Vararg{Integer}}, sizeB::Tuple{Integer,Vararg{Integer}})
415+
function matmul_size_check(sizeA::Tuple{Integer,Vararg{Integer}}, sizeB::Tuple{Integer,Vararg{Integer}})
416416
szA2 = get(sizeA, 2, 1)
417417
if szA2 != sizeB[1]
418-
strA = _vec_or_mat_str(sizeA)
419-
strB = _vec_or_mat_str(sizeB)
420-
B_size_len = length(sizeB) == 1 ? sizeB[1] : sizeB
421-
size_or_len_str_B = B_size_len isa Integer ? "length" : "size"
422-
dim_or_len_str_B = B_size_len isa Integer ? "length" : "first dimension"
423-
pos_str_A = LazyString(length(sizeA) == length(sizeB) ? "first " : "", strA)
424-
pos_str_B = LazyString(length(sizeA) == length(sizeB) ? "second " : "", strB)
425-
throw(DimensionMismatch(
426-
LazyString(
427-
lazy"incompatible dimensions for matrix multiplication: ",
428-
lazy"tried to multiply a $strA of size $sizeA with a $strB of $size_or_len_str_B $B_size_len. ",
429-
lazy"The second dimension of the $pos_str_A: $szA2, does not match the $dim_or_len_str_B of the $pos_str_B: $(sizeB[1])."
430-
)
431-
)
432-
)
418+
matmul_size_check_error(sizeA, sizeB)
433419
end
434420
return nothing
435421
end
436-
@noinline function matmul_size_check(sizeC::Tuple{Integer,Vararg{Integer}}, sizeA::Tuple{Integer,Vararg{Integer}}, sizeB::Tuple{Integer,Vararg{Integer}})
422+
@noinline function matmul_size_check_error(sizeA::Tuple{Integer,Vararg{Integer}}, sizeB::Tuple{Integer,Vararg{Integer}})
423+
strA = _vec_or_mat_str(sizeA)
424+
strB = _vec_or_mat_str(sizeB)
425+
szA2 = get(sizeA, 2, 1)
426+
B_size_len = length(sizeB) == 1 ? sizeB[1] : sizeB
427+
size_or_len_str_B = B_size_len isa Integer ? "length" : "size"
428+
dim_or_len_str_B = B_size_len isa Integer ? "length" : "first dimension"
429+
pos_str_A = LazyString(length(sizeA) == length(sizeB) ? "first " : "", strA)
430+
pos_str_B = LazyString(length(sizeA) == length(sizeB) ? "second " : "", strB)
431+
throw(DimensionMismatch(
432+
LazyString(
433+
"incompatible dimensions for matrix multiplication: ",
434+
lazy"tried to multiply a $strA of size $sizeA with a $strB of $size_or_len_str_B $B_size_len. ",
435+
lazy"The second dimension of the $pos_str_A: $szA2, does not match the $dim_or_len_str_B of the $pos_str_B: $(sizeB[1])."
436+
)
437+
)
438+
)
439+
end
440+
function matmul_size_check(sizeC::Tuple{Integer,Vararg{Integer}}, sizeA::Tuple{Integer,Vararg{Integer}}, sizeB::Tuple{Integer,Vararg{Integer}})
437441
matmul_size_check(sizeA, sizeB)
438442
szB2 = get(sizeB, 2, 1)
439443
szC2 = get(sizeC, 2, 1)
440444
if sizeC[1] != sizeA[1] || szC2 != szB2
441-
strA = _vec_or_mat_str(sizeA)
442-
strB = _vec_or_mat_str(sizeB)
443-
strC = _vec_or_mat_str(sizeC)
444-
C_size_len = length(sizeC) == 1 ? sizeC[1] : sizeC
445-
size_or_len_str_C = C_size_len isa Integer ? "length" : "size"
446-
B_size_len = length(sizeB) == 1 ? sizeB[1] : sizeB
447-
size_or_len_str_B = B_size_len isa Integer ? "length" : "size"
448-
destsize = length(sizeB) == length(sizeC) == 1 ? sizeA[1] : (sizeA[1], szB2)
449-
size_or_len_str_dest = destsize isa Integer ? "length" : "size"
450-
throw(DimensionMismatch(
451-
LazyString(
452-
"incompatible destination size: ",
453-
lazy"the destination $strC of $size_or_len_str_C $C_size_len is incomatible with the product of a $strA of size $sizeA and a $strB of $size_or_len_str_B $B_size_len. ",
454-
lazy"The destination must be of $size_or_len_str_dest $destsize."
455-
)
456-
)
457-
)
445+
matmul_size_check_error(sizeC, sizeA, sizeB)
458446
end
459447
return nothing
460448
end
449+
@noinline function matmul_size_check_error(sizeC::Tuple{Integer,Vararg{Integer}}, sizeA::Tuple{Integer,Vararg{Integer}}, sizeB::Tuple{Integer,Vararg{Integer}})
450+
strA = _vec_or_mat_str(sizeA)
451+
strB = _vec_or_mat_str(sizeB)
452+
strC = _vec_or_mat_str(sizeC)
453+
szB2 = get(sizeB, 2, 1)
454+
C_size_len = length(sizeC) == 1 ? sizeC[1] : sizeC
455+
size_or_len_str_C = C_size_len isa Integer ? "length" : "size"
456+
B_size_len = length(sizeB) == 1 ? sizeB[1] : sizeB
457+
size_or_len_str_B = B_size_len isa Integer ? "length" : "size"
458+
destsize = length(sizeB) == length(sizeC) == 1 ? sizeA[1] : (sizeA[1], szB2)
459+
size_or_len_str_dest = destsize isa Integer ? "length" : "size"
460+
throw(DimensionMismatch(
461+
LazyString(
462+
"incompatible destination size: ",
463+
lazy"the destination $strC of $size_or_len_str_C $C_size_len is incomatible with the product of a $strA of size $sizeA and a $strB of $size_or_len_str_B $B_size_len. ",
464+
lazy"The destination must be of $size_or_len_str_dest $destsize."
465+
)
466+
)
467+
)
468+
end
461469

462470
# We may inline the matmul2x2! and matmul3x3! calls for `α == true`
463471
# to simplify the @stable_muladdmul branches

0 commit comments

Comments
 (0)