인라인 함수는 호출 코드에 직접 통합되는 함수입니다.
인라인 함수 사용
정적 형식 매개 변수를 사용하는 경우 형식 매개 변수로 매개 변수화된 모든 함수는 인라인이어야 합니다. 이렇게 하면 컴파일러가 이러한 형식 매개 변수를 확인할 수 있습니다. 일반 제네릭 형식 매개 변수를 사용하는 경우 이러한 제한은 없습니다.
멤버 제약 조건을 사용하도록 설정하는 것 외에 인라인 함수는 코드 최적화에 유용할 수 있습니다. 그러나 인라인 함수를 과도하게 사용하면 코드가 컴파일러 최적화 및 라이브러리 함수 구현의 변경에 덜 저항할 수 있습니다. 따라서 다른 모든 최적화 기술을 시도하지 않는 한 최적화를 위해 인라인 함수를 사용하지 않아야 합니다. 함수 또는 메서드를 인라인으로 만들면 성능이 향상될 수 있지만 항상 그런 것은 아닙니다. 따라서 성능 측정을 사용하여 지정된 함수를 인라인으로 만드는 것이 실제로 긍정적인 영향을 미치는지 확인해야 합니다.
한 inline 정자는 최상위 수준, 모듈 수준 또는 클래스의 메서드 수준에서 함수에 적용할 수 있습니다.
다음 코드 예제에서는 최상위 수준의 인라인 함수, 인라인 인스턴스 메서드 및 인라인 정적 메서드를 보여 줍니다.
let inline increment x = x + 1
type WrapInt32() =
member inline this.incrementByOne(x) = x + 1
static member inline Increment(x) = x + 1
인라인 함수 및 형식 유추
존재는 inline 형식 유추에 영향을 줍니다. 인라인 함수는 정적으로 확인된 형식 매개 변수를 가질 수 있지만 인라인이 아닌 함수는 사용할 수 없기 때문입니다. 다음 코드 예제에서는 정적으로 확인된 형식 매개 변수 inline 인 변환 연산자가 있는 함수를 사용하므로 유용한 사례를 float 보여 줍니다.
let inline printAsFloatingPoint number =
printfn "%f" (float number)
inline 한정자가 없으면 형식 유추는 함수가 특정 형식을 사용하도록 강제합니다. 이 경우 int. 그러나 한정자를 사용하면 inline 함수도 정적으로 확인된 형식 매개 변수를 갖도록 유추됩니다. 한 inline 정자를 사용하면 형식이 다음으로 유추됩니다.
^a -> unit when ^a : (static member op_Explicit : ^a -> float)
즉, 함수는 float로의 변환을 지원하는 모든 형식을 허용합니다.
InlineIfLambda
F# 컴파일러에는 코드 인라인을 수행하는 최적화 프로그램이 포함되어 있습니다. 이 특성을 통해 코드는 InlineIfLambda 필요에 따라 인수가 람다 함수로 결정되는 경우 해당 인수 자체가 항상 호출 사이트에서 인라인되어야 함을 나타낼 수 있습니다. 자세한 내용은 F# RFC FS-1098을 참조하세요.
예를 들어 다음 iterateTwice 함수를 사용하여 배열을 트래버스하는 것이 좋습니다.
let inline iterateTwice ([<InlineIfLambda>] action) (array: 'T[]) =
for i = 0 to array.Length-1 do
action array[i]
for i = 0 to array.Length-1 do
action array[i]
호출 사이트가 다음과 같은 경우:
let arr = [| 1.. 100 |]
let mutable sum = 0
arr |> iterateTwice (fun x ->
sum <- sum + x)
그런 다음 인라인 및 기타 최적화 후에 코드가 다음과 같이 됩니다.
let arr = [| 1..100 |]
let mutable sum = 0
for i = 0 to arr.Length - 1 do
sum <- sum + arr[i]
for i = 0 to arr.Length - 1 do
sum <- sum + arr[i]
이 최적화는 관련된 람다 식의 크기에 관계없이 적용됩니다. 이 기능을 사용하여 루프 언롤링 및 유사한 변환을 보다 안정적으로 구현할 수도 있습니다.
호출 사이트의 람다 식에 인수가 바인딩되지 않는 코드 /warnon:3517 의 위치를 나타내기 위해 옵트인 경고(<WarnOn>3517</WarnOn>또는 속성InlineIfLambda)를 설정할 수 있습니다. 일반적인 경우에는 이 경고를 사용하도록 설정하면 안 됩니다. 그러나 특정 종류의 고성능 프로그래밍에서는 모든 코드가 인라인화되고 평면화되도록 하는 것이 유용할 수 있습니다.
커리 콜백 최적화
콜백을 인라인 처리할 수 없는 경우 반복된 심각도 적응을 방지하기 위해 F# 11은 다음과 InlineIfLambda함께 지원합니다.OptimizeClosureIfNotInlined
let inline foldItems
([<InlineIfLambda; OptimizeClosureIfNotInlined>] folder)
state
(items: 'T[]) =
let mutable total = state
for item in items do
total <- folder total item
total
함수는 인라인이어야 하고, 두 특성이 모두 있어야 하며, 콜백은 2~5개의 인수로 큐에 추가되어야 합니다. 알려진 람다는 인라인으로 연결할 수 있습니다. 불투명 콜백은 한 번 조정할 수 있습니다. 이를 위해서는 FSharp.Core 11 및 컴파일러 지원이 필요하지만 할당이 0이 보장되지는 않습니다.
인라인 함수 디버그
인라인 도우미를 한 단계씩 실행하려면 최적화 없이 컴파일하고 디버깅 정보를 유지합니다. F# 11은 다음 빌드에서 일반 호출을 선호합니다.
let inline addFee (fee: decimal) (amount: decimal) =
let total = amount + fee
total
let invoiceTotal = addFee 2m 40m
printfn "%M" invoiceTotal
// 42
샘플 프로젝트에서 중단점을 let total설정하고, 한 단계씩 addFee실행하고, 해당 인수를 검사합니다.
최적화된 빌드는 기본적으로 여전히 인라인으로 표시됩니다. 정적 확장이 필요한 다시 시작 가능한 코드 및 작업을 비롯한 일부 구문은 최적화 없이도 인라인되어야 합니다. 이전 동작을 요청하는 데 사용합니다 --always-inline .
라이브러리 간 인라인 확장 제약 조건
F# 11.2는 공용 확장 멤버를 사용하여 SRTP 요구 사항을 충족할 수 있습니다. 언어 설정, 범위 및 라이브러리 요구 사항에 대한 SRTP 제약 조건은 확장 멤버 를 참조하세요.
참고하십시오
.NET