Files
FESADev/docs/calculation-performance/t4-shell-optimization.md
T

14 KiB
Raw Blame History

Shell 계산 경로의 성능 변경

이 기록은 reduced-coordinate shell의 local 계산 변경과 근거를 구분한다. 전체 시간 목표와 최종 원본 비교는 PRD의 계약이며 아래의 단계 검사는 그 계약의 최종 합격을 대신하지 않는다.

계측과 변경의 연결

원본 meshfine shell의 기준 전체 실행은 6372.3256209초다. VTune 소프트웨어 샘플링의 별도 150초 부분 수집은 accepted increment 2 / time 0.2까지 포함한다. Jet*는 sampled CPU 133.466초(27.6%), malloc은 30.289초(6.3%)였다. EvaluateAssembly의 inclusive 257.862958 CPU초와 중첩 selector의 1.600014초는 겹치는 호출 경로이므로 더하거나 전체 경과 시간으로 바꾸지 않는다.

nonlinear_mitc4_shell.cpp의 모든 Jet는 기존에 값이 상수인 경우도 576-double Hessian을 영 초기화한 shared_ptr로 할당했다. 상수의 영 Hessian은 이제 읽기 전용 정적 영 배열을 참조하고 처음 쓰는 때만 기존 공유 storage를 할당한다. 읽기 전용 영 배열에는 trial 값이 없으며 동시 호출은 그 배열을 수정하지 않는다. 이미 할당된 Hessian의 복사/공유 수명은 그대로다. 현재 trial 이외의 형상·접선· 도함수 응답을 저장하거나 주소에 따라 재사용하는 cache는 추가하지 않았다.

후속 후보는 576-entry 반복문 앞에서 입력 read pointer와 fresh output pointer를 한 번씩 취득한다. fresh output은 단일 make_shared 할당을 유지하고 영 초기화를 생략한 뒤 576개 전체를 기록한다. operator+/-/*, scalar scale, Compose, Atan2의 모든 complete write와 MKL 거부 시의 NaN fill 뒤에만 결과를 읽거나 복사한다. 일반 부분 mutable write는 영 초기화를 유지한다. 상수의 nullptr 복사에는 별도 mutable 공유 객체가 없지만 실제 consumer는 복사된 상수 Hessian을 수정하지 않는다. 이미 할당된 결과의 shared copy와 입력 alias는 수정하지 않는다.

일반 행렬 연산의 MKL 경계

파일 / 함수 연산과 크기 변경
mitc4_shell.cpp::Stiffness, Congruence 5×20 strain의 BᵀCB, 20/4 local→24 congruence Matrix::Multiply와 private transpose-left MKL GEMM, 상삼각 결과를 그대로 대칭 복사
nonlinear_mitc4_inertia.cpp::CheckPhysicalMass 24×20 complement Gram·mass congruence, 20×20 Cholesky·inverse·reconstruction GEMM 및 기존 private LAPACK helper; 같은 positivity, reconstruction, 2^-32 conditioning gate 유지
nonlinear_mitc4_inertia.cpp::Evaluate 각 lumped mass-node의 6×3 coefficient Gram, velocity/position bilinear, 3방향 mass variation의 6×6 block 무할당 row-major transpose-right GEMM; 원래 point/node/row/column scatter와 가중 누적 유지
nonlinear_mitc4_shell.cpp::operator*, Compose, Atan2, DrillingEnergy ordinary 24×24 derivative outer products private OuterProduct의 row-major GEMM k=1, 기존 Jet storage에 직접 기록
hht_dynamic_algebra.cpp::BuildPhysicalSpace scaled free mass×analytic null 및 일반 complement congruence의 sparse contributions entrywise compact-diagonal MKL products 뒤 원래 CSR/COO 순서 누적; full global dense matrix 없음
hht_dynamic_algebra.cpp::CheckLocalMass nonempty nodal physical block, 크기1–6 MKL Cholesky/inverse; 동일 inverse infinity norm과 2^-32 conditioning 검사
hht_dynamic_algebra.cpp::CheckRegularity, hht_reduced_operators.cpp::CheckGraphRegularity scalar null stiffness metric와 gradient×null projection MKL GEMV/dot 또는 entry products, 기존 fresh factorization/모든 unit RHS/residual/condition gate 유지
hht_reduced_operators.cpp::ContractConstraintHessian failure-only bilinear replay의 sparse Hessian entries 두 MKL diagonal product 뒤 기존 left association/entry order sum

Outer product는 배열 copy나 Matrix 객체를 만들지 않는다. 크기·integer range· nonempty null storage를 검사하며 비유한 입력은 MKL 호출/출력 쓰기 전에 거부한다. 유한 입력의 곱 overflow는 후속 owner finite gate가 판단한다. Jet consumer는 거부된 operand의 결과를 NaN으로 표시하고 원래 equilibrium/constraint finite 실패를 반환한다. 직접 scalar product로 계산하는 fallback은 없다.

CholeskyLowerAndInverse의 optional private failure reason은 validation 전에 kNone으로 초기화된다. factor pivot/finite 실패와 inverse/finite 실패를 구분하여 기존 positive-mass와 ill-conditioned-mass 진단을 유지한다. 실패에서는 lower와 inverse output candidate를 교체하지 않는다. 기존 default-nullptr consumer의 bool 의미는 그대로이며 live inverse 실패를 발생시킨 검사는 아직 없다.

Element-local dense work의 ScopedLocalDenseThreads는 caller TLS 요청이 default 0일 때만 1을 적용한다. caller의 양수 override는 유지하고 정상 반환과 unwind 뒤 원래 default를 복원한다. 전역 MKL/OpenMP 정책이나 이후 global solve에는 영향을 주지 않는다. 각 scalar metric scope는 MKL 호출 뒤 끝나며 global PARDISO를 포함하지 않는다. 현재 후보의 실제 비용과 복원 검사는 아래 단계 검증 기록으로 구분한다. TLS default 0, caller override 우선순위와 저장한 값을 복원하는 동작은 Intel 2026 thread-local reference의 계약을 따른다.

Hessian의 합산 순서와 ordinary product는 별도다. 곱셈 Jet는 원래의 left.second * right.value + outer1 + outer2 + left.value * right.second를 유지한다. Compose와 Atan2는 계수×gradient를 먼저 계산하여 원래 left association을 유지한 뒤 outer product를 계산한다. GEMM의 연산과 signed-zero 결과는 원래 scalar 구현의 bit 동일성을 주장하지 않으며 접선/방향/혼합 도함수의 수치 검토 대상이다. 일반 24×24 연산을 AD라는 이유로 특수 정밀도 예외로 처리하지 않는다.

유지하는 특수 연산

파일 / 함수 크기·정밀도·이유 검증 범위
nonlinear_mitc4_inertia.cpp::Jet, ExpSkew, LeftJacobian 3개의 nodal rotation coordinate에 대한 최대 3차 analytic derivative; 3×3×3 tensor finite rotation, inertia force/position/velocity tangent와 null·momentum oracle
hht_reduced_operators.cpp::BasisValue, fixed basis 생성 normalized high+low 및 outward radius; 3-vector basis certificate fixed chart/radius replay·partial-boundary·selector transversality
hht_reduced_operators.cpp::RateSum, GradientDot, reduced block 누적 sparse support의 원래 순서 Neumaier correction cancellation, full defect, mixed rates·channel acceptance
nonlinear_mitc4_inertia.cpp::InertiaSum kinetic force/energy/momentum의 원래 순서 compensated contraction 독립 inertia oracle와 omission 검출, 좌표/단위 변화
shell의 fixed3 coordinate tensor/rotation 변환 좌표·director·chart의 3-vector 또는 3×3 연산 rigid motion/objectivity·principal chart 실패
hht_dynamic_algebra.cpp::BuildPhysicalSpace의 analytic nodal basis Gram, InitializeAcceleration의 force projection/lift translation 1계수 또는 단일 절점의 최대3 rotation components; 현재 assembly의 nodal frame에 대한 Float64 좌표 변환 서로 다른 node의 basis support는 disjoint, 같은 node의 최대3-vector inner product만 사용; excluded fixed rows·원래 association·초기 acceleration 진단 순서 유지

보상 누적과 interval/basis 인증은 일반 Float64 GEMM으로 접어 수치 의미를 잃지 않는다. hht_reduced_operators.cpp::GradientDot, Lift, ProjectPhysical, ReconstructPhysicalRates, AssembleAugmentedReducedSystem의 support contractions는 원래 entry 순서의 Neumaier correction과 high+low/outward fixed-basis certificate를 유지하는 예외다. Plain sum과 달리 partition cancellation에서 소실되는 1을 유지하는 ReconstructsRatesAcrossSelectedPartitionCancellation 및 augmented full-model defect 검사가 해당 의미를 검증한다. 일반 24×24 outer와 mass matrix 제품은 이 예외로 묶지 않는다. BuildPhysicalSpace의 좌표 basis는 현재 assembly의 analytic null로 각 호출에서 생성한다. 초기화는 initial assembly를 사용하고 후속 질량 인증은 해당 현재 assembly를 사용한다. 실행 전체의 fixed initial chart와 같은 자료라고 판단하지 않으며 다른 trial에 basis/응답을 재사용하지 않는다.

단계 검증 상태

변경 전 clean source 8c7c41729eb9eaa904f6739b54d34c37b1bd555f의 fresh MSVC Debug configure/build는 native 0, local shell/inertia/reduced/math 70개는 모두 PASS다. 별도 MITC4 linear kernel·mass·recovery 20개도 native 0으로 모두 PASS다. Mixed-time actual shell fixture는 144.84초에 정상 통과했으며 중단되지 않았다. 원래 실행 기록과 linear 실행 기록을 보존한다.

첫 후보 build의 Status 기본 생성자 오류(native 2)는 별도로 보존하고 Status::Ok 초기화로 수정했다. 수정 후보의 configure/build는 native 0이고 91개 중 90 PASS, HhtReducedEmbedding.ReconstructsActualShellRatesWithMixedTimeLoad는 180초 timeout으로 미통과다. 전체 CTest native 8과 실제 종료 상태를 보존한다. 이 Debug 비용 악화를 Release 개선으로 표시하지 않는다. 이는 candidate-local-fixed snapshot의 결과다. Read pointer hoist, fresh output의 단일 allocation/full overwrite, 별도 이름의 local TLS scope와 추가 coverage를 적용한 packed-output-mkl-coverage 결과는 별도로 기록한다.

기존 Korean compiler 환경의 Ninja header prefix가 mojibake이고 actual dependency graph가 0개인 사실을 확인했다. 그 build의 직접 변경 source/검사 결과는 보존하되 header consumer 전체 재빌드를 입증한다고 해석하지 않는다. 설치된 compiler의 locale fallback 때문에 VSLANG=1033만으로 해결되지 않는다는 root의 후속 근거가 있다. 정확한 include prefix를 지정한 ignored metadata helper의 별도 probe 뒤 full fresh build에서 actual Ninja header deps를 확인했다. 공용 preset/flag나 source object를 바꾸어 혼합하지 않는다.

후속 packed-output-mkl-coverage snapshot의 source SHA-256은 source manifest에 있다. Corrected-prefix fresh configure/build는 각각 native 0이고 eigen_reduction.cpp.obj의 실제 dependency inventory에 dense_blas_internal.h가 포함되어 있다. 기존 Cholesky/eigen consumer, local tangent/objectivity/patch·inertia, fixed chart·channel/failure·boundary·MKL scope/shape/finite 검사 105/105 PASS, native 0, CTest 36.94초다. 별도 mixed-time fixture도 1/1 PASS, native 0, fixture 60.69초다. 실행 기록, 검사 로그, mixed-time 기록을 보존한다. 이 106개 결과는 전체 Debug/원본 비교/시간수렴을 통과했다는 뜻이 아니다.

첫 Release 보조 configure는 runtime DLL PATH를 compiler 탐색보다 앞에 두어 icx가 선택되었고 libircmt.lib 없음으로 native 1 실패했다. 수치 실행은 없었으며 실패 자료/cache를 보존한다. 동일 설치 MSVC cl을 명시한 별도 fresh directory의 Release configure/build 97 edges는 native 0이다. 보조 실행 기록을 보존한다.

Jet 보조 측정은 frozen 8c7c417의 실제 Jet source span과 현재 production nonlinear_mitc4_shell.cpp를 같은 translation unit에 두고 현재 source의 Release library와 연결했다. 동일 입력·flags로 각 variant의 3000-product loop를 워밍업 없이 한 번씩 측정했다. 모든 value/gradient/Hessian/directional/mixed coefficient 및 checksum이 같고 실제 native 0, scope 안 effective threads 1, 종료 뒤 caller TLS 복원 true다. 정확성 대조는 모든 타이밍 후 수행했다.

보조 variant 3000-product loop 경과 시간
frozen original 0.0025384초
MKL candidate / default 8 0.0082295초
MKL candidate / element scope 1 0.0029779초

Scope는 새 MKL kernel의 default-thread 비용을 줄이지만 이 dense nonzero kernel 자체가 원래 구현보다 빠르다는 근거는 아니다. Scope 후보도 original보다 약17% 느리다. 전체 모델의 준비·조립·allocator·선형 해법·출력 비용과 최종 100초 목표는 이 보조 값으로 판단하지 않는다. 실제 production의 Constant/Jet allocation 빈도 감소는 최종 VTune에서 확인해야 한다.

Standalone include의 vendor C4819 경고는 보존했다. 실제 production과 같은 /W4 /WX /external:W0로 compile/link만 추가 실행하여 native 0/경고 없음이고 수치 타이밍은 반복하지 않았다. 측정된 exe는 별도 원본 copy로 보존했으며 추가 exe의 .text SHA-256이 동일한 것을 확인했다. 기계어/실행 파일 보존 기록을 따른다. 전체 Debug·원본 비교·C08 current grid·VTune 최종 수집·공식 단일 시간 측정은 이 단계에서 실행하지 않았다. 변경되지 않은 reference와 tolerance를 사용해야 한다.