Files
FESADev/docs/calculation-performance/mkl-coverage.md
T

258 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MKL 적용 범위와 수명 근거
FEM-REQ-PERF-004/005/007/009의 T2 구현 기록이다. 공통 요구사항·물리·수치
기준과 reference는 변경하지 않았다. T3/T4 인계 목록은 해당 owner가 완료한
실제 diff와 검사를 통합한 뒤 갱신한다. 이 기록만으로 전체 production 적용이나
세 모델의 공식 시간 목표 통과를 주장하지 않는다.
## 공통 연산 경계
| 위치 | 연산 / 실제 private 호출 | 유지하는 의미 |
| --- | --- | --- |
| `math/matrix.cpp::Multiply` | dense gemv/gemm, `cblas_dgemv/dgemm` | 기존 shape/empty/checked MKL_INT 및 새 actual operand finite preflight |
| `math/vector.cpp` | Dot/Scale/Axpy와 copy, dense BLAS | 기존 공개 값·실패 의미 유지 |
| `math/dense_blas_internal.cpp::MultiplyTransposeLeft` | transpose storage copy 뒤 `Matrix::Multiply`; diagonal DSBMV(k0); LAPACK dpotrf/dtrtri | transpose-left shape 확인; ordinary product는 MKL |
| `math/sparse_matrix.cpp::Multiply` | `mkl_sparse_d_create_csr` → `mkl_sparse_d_mv` → destroy | canonical CSR와 structural zeros, general full matrix, zero-based index |
| `solvers/linear/mkl_pardiso_solver.cpp` | PARDISO SPD factorization/solve | 기존 경로와 scoped n=1 policy |
| `solvers/linear/mkl_pardiso_tangent_solver.cpp` | fresh phase 11/22, solve 33 | 새 분해 전 release; 실패 뒤 stale 사용 금지; 동일 성공 분해의 여러 RHS 허용 |
| `results/global_equilibrium_recovery.cpp` | full K*d, free/constrained masked RHS의 각 K*d | Kff*df/Kfc*dc scale를 별도로 유지; 원래 free rows만 norm 판정 |
| `analysis/linear_frequency_procedure.cpp` / `solid_frequency_procedure.cpp` | original/whitened pencil sparse action, dense Dot | original-pencil finite/independent residual/energy/Gram 검사 유지 |
| `solvers/eigen/mkl_feast_eigen_solver.cpp` | independent scaled full/mass/mirrored sparse actions; QR ddot/daxpy | FEAST actual 호출·count/solve budget·seed/Householder 절차 유지; backend residual로 독립 residual 대체하지 않음 |
| `analysis/eigen_reduction.cpp` | nodal/block congruence, mode restoration, nodal mass action | nodal analytic null split과 scaled original pencil 유지 |
| `analysis/thermal_transient_algebra.cpp` | BE RHS entry의 compact diagonal DSBMV, reduced/full/dissipation CSR actions | raw old constrained state·signed temperature·actual delta·independent interval companion 보존 |
| `elements/euler_beam_3d.cpp` | B*d, BᵀDB, TᵀKT, interpolationᵀq | 2 Gauss points·closed stiffness invariant·local force/section identity 유지 |
### Sparse 단발 자원
입력 의존성은 현재 matrix의 전체 CSR shape/index/value와 현재 RHS이다.
`Validate()`가 canonical CSR와 finite coefficient를 확인한 뒤 actual `MKL_INT`
폭에 맞춰 rows/columns/nnz/각 index를 checked 변환한다. 공개 `size_t` storage는
변경하지 않고 기존 private `ToMklSize`를 재사용한다. 이 설치의 ILP64를 public
API에 하드코딩하지 않는다.
호출 stack이 변환 index 배열·복사 values와 handle을 소유한다. handle은 배열 뒤에
생성되며 RAII destroy가 배열 소멸보다 먼저 실행된다. MKL이 CSR 배열을 참조한다는
[Intel create CSR 계약](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2026-0/mkl-sparse-create-csr.html)을 따른다.
직접 private values 복사는 const-cast 없이 const 동시 호출을 분리한다.
호출 종료가 invalidation이며 지속 handle/cache가 없다. 저장량은 단발
`(rows+1+nnz)*sizeof(MKL_INT)+nnz*sizeof(double)` 및 output이다.
측정 근거 없는 symbolic/persistent cache는 채택하지 않았다. 아래 n=1 PARDISO의 제한된 TLS 정책만 실제 baseline/보조 근거로 채택했다.
0 rows/0 columns/no entries는 검증과 index range 확인 뒤 zero vector를 반환한다.
nonempty matrix의 구조상 빈 row는 MKL 결과의 zero row다. Copy/move/assignment는
공개 CSR 값 storage 수명만 갖고 backend pointer를 보관하지 않는다. Moved-from
불완전 CSR은 사용 전에 validation에서 거부되므로 indexing UB로 진행하지 않는다.
backend failure는 scalar fallback이나 성공 candidate 없이 `runtime_error`로,
integer overflow는 `length_error`로 전달한다. vendor enum/원시 오류 번호는 공개하지
않는다. `GlobalEquilibriumRecovery`와 frequency/eigen/thermal consumer는 해당
새 실패를 `Status/Result`로 변환하며 이전 state/history/final 결과를 commit하지 않는다.
실제 allocation/backend fault를 강제한 native 시험은 실행하지 않았다. 해당
실패 branch의 fallback 부재·exception 변환·RAII 해제는 정적 검토 범위이며,
일반 실패/반복·copy/move·동시 const 호출과 bad RHS 복구는 실제 검사 범위다.
### Finite의 owner
CSR coefficient와 모든 RHS는 MKL 호출 전 math에서 finite 검증한다. 비유한 RHS는
기존 값 반환/exception 형식의 `invalid_argument`로 거부하며, public signature는
변경하지 않는다. Finite-input product overflow는 consumer의 기존 output finite
검증으로 실패한다. Empty/zero shape도 입력 finite/shape/range 검증을 유지한다.
밀집 GEMV/GEMM은 `Matrix::Multiply`에서 양쪽 matrix storage와 Vector RHS를
호출 전에 finite 검사한다. Private transpose-left 연산도 이 경계를 사용하며
비유한 입력은 `invalid_argument`로 거부한다. Eigen reduction·frequency·FEAST
owner는 이를 기존 Result 실패 형식으로 변환한다. MakeLift의 실제 basis와
scaled operand, FEAST의 normalized phi와 mass_modes도 dispatch 전에 검사한다.
Production caller finite 입력은 별도로 확인한다. Recovery는 기존
`IsFiniteVector`→Multiply→finite output 순서를 유지한다. Linear frequency의 physical
및 whitened x, solid frequency의 raw/normalized mode는 finite-first이며, FEAST가
반환한 벡터의 finite gate도 기존대로 유지한다. Thermal은 기존 Validate·solver
candidate finite와 interval enclosures를 사용한다. Thermal RHS의 각 entry는
`(c/delta)*(old-g)-k*g`라는 원래 association을 먼저 계산한 뒤 원래 row 순서로
누적한다. 두 행곱을 별도로 합산한 뒤 빼는 후보는 stable b=4를 잃어 기존
Cancellation 검사를 실패했으므로 폐기했다. 현재 private diagonal MKL은 O(nnz)
compact band k=0 storage로 entry별 곱만 계산한다. Exact companion과 construction
error·gamma·underflow certification·free/reaction 판정은 그대로다.
비유한 product를 정상값으로 clamp하거나 tolerance를 완화하지 않는다.
### PARDISO 수명
현재 구현 그대로 `release → CSR/shape/width 확인 → private arrays → phase11 → phase22`
를 수행한다. 값/pattern이 달라지면 `FactorizeFresh`를 다시 호출한다. 새 singular
분해 실패 뒤 `SolveCorrection`은 not-factorized이며 caller correction은 보존된다.
잘못된 RHS의 실패는 output 보존과 유효한 기존 matrix 분해의 수명을 구별한다.
여러 RHS는 같은 성공 분해의 phase33을 사용할 수 있다. 새로운 symbolic 재사용이나
다중 RHS framework를 도입하지 않았다.
### One-equation PARDISO의 scoped 자원 정책
[T1 실제 VTune](verification.md)의 OMP worker/spin 비용과 아래 toy n=1 lifecycle
근거로, SPD/Tangent의 `CallPardiso`에서 **현재 retained equation_count=1**인 경우만
호출의 기본 thread 수를 1로 제한한다. Phase 11/22/33/−1 각각의 호출 범위다.
`mkl_set_num_threads_local(1)`의 이전 TLS override가 0일 때만 1을 유지하고,
범위 종료 시 0을 복원한다. 이전값이 비영이면 즉시 그 값을 복원하여 호출자의
override로 backend를 실행한다. n=0 또는 n≥2, 전역 MKL/OpenMP 요청, dispatch,
iparm·pivot/scaling·regularization·acceptance는 변경하지 않는다.
계측하지 않은 더 넓은 size threshold는 채택하지 않았다.
Release는 이전 factor의 retained count, 새 factor는 새 count를 사용한다.
따라서 작은 matrix의 release 뒤 큰 matrix 호출에 설정이 남지 않는다.
외부 MKL/OMP 요청은 baseline과 같은 8/dynamic FALSE지만, 소스의 실제 자원
정책은 기본 설정의 1×1 호출에서 달라진다. 두 조건을 구분해 보고한다.
Phase 성공·오류·exception, 잘못된 RHS와 동시 호출에서 TLS 복원과 candidate
보존을 검사한다. Native process crash는 C++ RAII unwind를 보장하지 않는다.
종료한 process의 TLS 설정은 다음 실행이나 전역 환경에 남지 않는다.
### Baseline PARDISO heap failure와 제한
기존 static partial fixture는 full 24×24/free 1×1이다. `backend-isolation`의
SpMV-only 생성·곱셈·해제 1,000회는 native 0이었다. PARDISO-only 100회 예정
실행은 native `−1073740940 (0xc0000374)`로 중단됐다. 별도의 반복 static
fixture도 iteration 3에서 같은 heap 손상을 재현했다.
새 SpMV 수명 회귀와 분리해 기록하며 이 실패를 검사 통과로 표시하지 않는다.
같은 독립 진단 소스를 T1의 기존 Release library에
`/O2 /Ob2 /MD /DNDEBUG /Zi`로 link해 baseline을 대조했다. 기본 8-thread
실행은 61회 완료 뒤 62회에서 같은 native crash가 발생했다. Scoped 1-thread는
100회 native 0이며 각 범위 종료 뒤 effective 8 복원을 기록했다.
현재 Debug `/Od /Ob0 /MDd /RTC1 /Zi` 대조의 8/1-thread는 각각 100회
완료했지만, 이전 Debug 진단의 iteration 2/3 crash도 보존한다. 간헐적 실패이므로
100회 통과를 vendor 문제의 해결 확정으로 쓰지 않는다. Debug/Release도 구분한다.
Ordered full/free CSR offsets·columns·raw double bits와 RHS의 input SHA는 양쪽
`CC7E72000783E9694BAF76627D95AB7B420A31198B210B5A60C7ACE93E5E2258`로같다.
ILP64·mtype 2·실제 pardisoinit 기본 controls(26 checker/34 zero-based 포함), 동일
MKL/runtimeDLL hash는[recorded-probes metadata](../../.harness/performance/t2/recorded-probes-metadata.json)와
[native 기록](../../.harness/performance/t2/recorded-probes-native.json)에 있다.
기존 PARDISO/backend 영역의 실패를 실제 baseline에서 재현했지만 내부 원인은 미확정이다.
[Intel release notes](https://www.intel.com/content/www/us/en/developer/articles/release-notes/onemkl/2026.html)의
non-AVX2 PARDISO sporadic pivoting issue는 조사 근거이며 현재 원인을 확정하지 않는다.
설치·dispatch·전역 registry/pageheap은 변경하지 않았다.
같은 toy n=1 보조 실행에서 default 8-thread는 11회 뒤 crash/0.24초,
scoped 1-thread는 100회 완료/0.15초였다. 입력 준비와 로그를 포함한 보조 자료이며,
실패와 표본 수 차이가 있어 공식 모델의 개선 배수나 시간 목표 판정에 사용하지 않는다.
[비용기록](../../.harness/performance/t2/tiny-pardiso-cost-native.json)에 실제 범위를 남겼다.
## 특수 정밀도 개선과 예외
T1의 실제 Hex8 VTune stack은 `TwoSum → Add → Multiply → hex8_high_low::operator*`
비용 및 frexp/ldexp 분류 비용을 확인했다. T2는 arithmetic association과 underflow
정책을 바꾸지 않고 두 helper만 개선했다.
- `high_low_arithmetic.h::IsNormalized`: finite와 canonical exact-zero guard 뒤
`RN(high+low)==high`. 이 경우 기존 TwoSum의 bridge=0/restored=high/error=low이며,
반대 방향도 기존 predicate의 high equality가 같은 조건이다. overflow/nonfinite와
noncanonical signed zero를 먼저 거부한다.
- `LowestBitExponent`: IEEE binary64를 memcpy로 읽어 정상은
`(encoded exponent−1075)+trailing(implicit53bits)`, subnormal은
`−1074+trailing(fraction)`으로 계산한다. 부호를 제외하고 actual least bit를 보존한다.
TwoProduct의 least-bit-sum < −1074 거부와 FMA residual·TwoSum 정규화는 그대로다.
- zero/low-zero shortcut, nonzero multiplication association 변경은 채택하지 않았다.
[독립 수치 검토](../../.harness/performance/t2/arithmetic-numerical-review.md)는
위 두 helper proof/source 범위 PASS이며 실제 검사/속도와 전체 MKL diff 검토를
대체하지 않는다. Frozen original oracle는 pinned `b4fc1bb`의 원본이며 include guard와
namespace만 바꾼 test 전용 `high_low_arithmetic_original.h`이다. 실제 모든 정상
exponent×53 trailing-bit×양 부호, subnormal boundaries, signed zero/ties/overflow/
invalid/raw random 입력의 bit 대조 및 기존 analytical checks를 실행했다.
| 파일 / 함수 | 연산·크기·정밀도 | 예외 이유 / 검사·owner |
| --- | --- | --- |
| `math/high_low_arithmetic.h` 전체, `elements/hex8_high_low.cpp::EvaluateHighLow` | normalized binary64 high+low, 3×3 tensor 및 24×24 pair tangent | ordinary Float64 BLAS로 low/tail rejection을 잃을 수 없음; frozen oracle/Hex8HighLow·T3 |
| `elements/hex8_geometry.cpp`의 interval/relative coordinate 인증 | 3×3 inverse/Jacobian 및 outward interval | whole-cell certificate·직접 geometry predicate 보존; Hex8 geometry 검사·T3 |
| `elements/hex8_element.cpp` gradient/inverse·F/S/P/FFT/stress의 3×3 tensor | fixed3-coordinate contraction | 3-coordinate geometry/constitutive 의미; 24×24 ordinary tangent는 이 예외로 일괄 분류하지 않음·T3 |
| `elements/finite_rotation.cpp` Rodrigues/skew/invariant | fixed3×3 axis coordinate | 좌표 rotation/invariant; finite rotation 검사 |
| `analysis/eigen_reduction.cpp::MakeLift` analytic director/frame basis와 null-coordinate checks | fixed6 nodal coordinates, 최대6 positive basis | 고정 director/frame의 analytic 좌표 선택만 예외. 일반 mass whitening/Cholesky/inverse/congruence/reconstruction은 MKL 전환·EigenReduction |
| `elements/thermal_shell.cpp` shape/metric contraction | fixed4 shape·fixed3 gradient·2D metric, separable integration coefficient | local coordinate/shape quadrature; global capacity/conduction actions는 MKL·thermal local oracle |
| `analysis/thermal_transient_algebra.cpp`의 `I`/Add/Mul/Sub/Div/Norm/Error/Roundoff/Tiny | outward interval·construction/underflow enclosure | floating product와 분리된 정확대수 인증, gamma/epsilon/limit 변경없음·TransientHeatProcedure/ThermalPhysics |
| `analysis/hht_reduced_operators.cpp` Projection/Embed/Sum, BasisValue, reduced blocks | compensated sums 및 outward basis radius | low/error compensation 유지, ordinary Hessian/product는 T4 판별/전환 |
| `analysis/hht_dynamic_algebra.cpp` AddCompensated·constraint radius 및 3-vector director dot | compensated error·fixed coordinate | 승인 N3/N7·scale 인증; 일반 CSR contraction과 구별·T4 |
| `elements/nonlinear_mitc4_shell.cpp` / `nonlinear_mitc4_inertia.cpp` Jet 산술 | analytic derivative jets, fixed3 rotation | AD derivative association/coordinate 의미; ordinary24×24 Hessian/dense congruence blanket 예외 금지·T4 |
| `io/hdf5/nonlinear_hdf5_results_writer.cpp` spatial moment transform | fixed3×3 rotation coordinate | 공개 generalized/spatial quantity 변환 보존·T4 |
## T3/T4 인계
전수 검색의 raw 위치 목록은 [ordinary-product-audit](../../.harness/performance/t2/ordinary-product-audit.txt)다.
검색은 +=*만으로 완료하지 않고 Multiply·중첩 루프와 각 함수의 precision/owner를
함께 확인했다. 이 목록은 후속 diff에서 갱신해야 한다.
- T3: Hex8 pair tangent/relative geometry/mean-volume certification은 pair/interval
예외로 유지한다. Float64 24×24 response/tangent의 일반 contractions와 procedure
직접 products는 ordinary MKL 적용 여부를 확인한다.
- T4: `mitc4_shell.cpp::` transformation congruence(기존241 주변), strainᵀCstrain
stiffness(기존635 주변), `nonlinear_mitc4_inertia.cpp` complement Gram/projection
(기존449/456), `hht_reduced_operators.cpp` bilinear Hessian action(기존620),
reduced block/gradient products(기존970 이후), `hht_dynamic_algebra.cpp` 일반
stiffness projection(기존442)은 MKL 또는 구체적인 compensated 예외 근거가 필요하다.
`Jet*`의 derivative array 크기가24라는 이유만으로 모든24×24 Float64 products를
특수 정밀도 예외로 분류하지 않는다.
- 공통 recovery/eigen/thermal/beam은 T2 확장 owner로 직접 변경했다. Shared
assembly tuple reduction/source identity와 task별 CMake 등록은 root owner이며 변경하지 않았다.
## 실제 검증과 남은 작업
Parent artifact `.harness/performance/t2/`는 worktree cleanup 뒤에도 남는다.
각 native JSON은 argv/cwd/실제 exit와 source 또는 snapshot 구분을 보존한다.
아래 링크는 통합한 저장소의 feature 문서 위치를 기준으로 한다.
| 실행 범위 / source | 결과 | 실제 기록 |
| --- | --- | --- |
| 최초 Debug build | include 누락 exit2; 수정 뒤 build0 | `build-debug-initial-failed.txt`, `build-native-initial-failed.json` |
| 초기 개발 snapshot | core43/43·consumer71/71 PASS; whole-source hash 없는 precommit 자료 | `core-native.json`, `consumer-native.json` |
| Extended66 개발 snapshot | 64 PASS·1 thermal FAIL·1 large-mesh interrupted; whole native−1 | `extended-native.json`, `extended-checks.txt`, `extended-interruption.json`, `extended-cleanup.json` |
| 59c8e93 후보100개 | 99 PASS·열 RHS 상쇄1 FAIL; native8 | `final-native.json`, `final-checks.txt` |
| Thermal/finite/Gram/whitening 수정 snapshot82개 | 82/82 PASS; native0 | `corrected-native.json`, `corrected-checks.txt` |
| 후속 eigen20개 | 19 PASS·기존 PARDISO heap fixture1 native crash; native8 | `null-products-native.json`, `null-products-checks.txt` |
| 770fa2a scoped-policy 후보 | build0·99/99 PASS; native0 | `policy-build-native.json`, `policy-native.json` |
| 9c4e685 중앙 dense finite 후보 | build0·120/120 PASS; native0 | [build](../../.harness/performance/t2/finite-build-native.json), [native](../../.harness/performance/t2/finite-native.json), [log](../../.harness/performance/t2/finite-checks.txt) |
| 6fc7011 tests-only delta | build0·1↔2 retained-size 전환2/2 PASS; native0 | [build](../../.harness/performance/t2/transition-build-native.json), [native](../../.harness/performance/t2/transition-native.json), [log](../../.harness/performance/t2/transition-checks.txt) |
`MklPardisoSolver.SingleEquationScopeTransitionsBetweenRetainedSizes`와
`TangentSolver.SingleEquationScopeTransitionsBetweenRetainedSizes`는 각각
1→2→1 factorize/solve와 old/new retained count별 TLS 복원을 직접 확인한다.
동시 default TLS의 성공→다른값→bad RHS→새 분해 실패→stale solve 거부는
`SingleEquationPolicyPreservesLifecycleAndConcurrentTls` 및
`SingleEquationScopeRestoresTlsAcrossFreshFailureAndReuse`에서 확인한다.
Caller의 비영 TLS override·exception unwind와 큰 크기 정책은
`DenseBlasInternal.SingleEquationScopeRestoresTlsAndRespectsOverrides`의 직접 관찰이다.
SpMV destroy/PARDISO release-error를 live 주입한 검사는 미실행이다. 유효 handle에서
이를 안전하게 발생시킬 근거가 없고 production mutable fault hook은 추가하지 않았다.
정상 release·분해 오류 후 release·반복 및 크기 전환은 실제 검사이며, 원시 release
오류 분기의 candidate 실패 전달과 자원 수명은 독립 정적 검토 범위다.
9c4e685 production source의 [독립 conformance 재검토](../../.harness/performance/t2/source-conformance-review.md)는 PASS다. 이후 6fc7011은
검토자가 요청한 transition tests-only delta이며 production source는 같다.
High+low 두 helper의 독립 proof는 앞 절의 실제 보고서와 연결했다.
검토 PASS와 actual execution PASS는 서로 대체하지 않는다.
최초 실패·상쇄 회귀·간헐적 heap 실패·중단 자료를 삭제하거나 현재 PASS로 바꾸지 않았다.
전체 MSVC Debug/CTest, 원본3+Hex8 필수5 비교, VTune 최종 raw 및 공식
no-warmup/one-measurement 평가는 T5에서 미실행 항목을 완료해야 한다.
Task source를 fresh build했으며 다른 source의 object를 수동 복사하지 않았다.
Baseline-linked auxiliary는 root가 승인한 보존된 T1 Release library를 직접 link하고
그 flags/runtime/input을 별도로 기록했으므로 현재 Debug evidence로 대체하지 않는다.
High+low standalone 보조 microbenchmark는 같은 compiler/한 exe에서
original/optimized 각400000 products를3회 대조했다. Original은
0.129315/0.129951/0.129560s, optimized는0.069739/0.070177/0.068700s이며
모든 checksum이 같고 native0이다.
[보조기록](../../.harness/performance/t2/microbench.jsonl)과
[native](../../.harness/performance/t2/microbench-native.json)는 helper 비용 근거이며
3모델의 공식 wall 평가를 대체하지 않는다.
CSR consumer 전수 보강 검색은
[csr-consumer-audit](../../.harness/performance/t2/csr-consumer-audit.txt)에 있다.
`assembly/load_assembler.cpp::EffectiveFreeRhs`의 Kfc*dc는 root owner가 T2 통합 뒤
entrywise MKL diagonal products와 기존 개별 product/ordered row-sum finite gate로
연결한다. 이 공유 파일은 T2가 수정하지 않았다. 최종 production 전수 완료는
이 인계와 T3/T4 일반 연산 적용까지 확인해야 한다.
최종 source/test hash·production 검토 이후 source 변경 없음·874개 검사 discovery native0은
[final-source-manifest](../../.harness/performance/t2/final-source-manifest.json)에 기록했다.
[final CMakeCache](../../.harness/performance/t2/final-CMakeCache.txt)는 actual dependency와 Debug flags를 보존한다.
Whole changed-file clang-format dry-run은 기존 및 후보 formatting 위반으로 exit1이었다.
[실제 기록](../../.harness/performance/t2/clang-format-native.json)을 보존하며 formatter PASS로 보고하지 않는다.