Files
FESADev/docs/operations.md
T
2026-10-18 15:06:44 +09:00

8.3 KiB

환경 준비와 실행

준비 순서

저장소 root에서 VS x64 개발 환경을 사용한다. 직접 프로젝트는 v145 toolset과 Windows SDK를 요구한다. 필요한 로컬 설치는 MKL·TBB·HDF5·OpenMP/Intel runtime과 승인된 GoogleTest source checkout이다. CMake 경로에는 추가로 CMake 3.25 이상과 Ninja가 필요하다. Dependency 설치·다운로드·외부 source 수정은 아래 명령에 포함되지 않는다.

직접 MSBuild 설정은 다음 환경변수 또는 ignored msvc/Fesa.Local.props로 주입한다.

변수 값의 의미
FESA_GTEST_SOURCE_DIR googletest/include와 source를 포함한 승인된 checkout root
FESA_MKL_ROOT MKL의 include·lib·runtime을 포함한 설치 root
FESA_TBB_ROOT TBB 설치 root; Debug와 Release runtime을 구분한다.
FESA_HDF5_ROOT HDF5 C library의 include·lib·runtime 설치 root
FESA_OMP_ROOT Intel OpenMP library와 runtime 설치 root
MKL_DIR·TBB_DIR·HDF5_DIR CMake에서만 사용하는 각 CONFIG package 디렉터리; 설치 root와 혼동하지 않는다.

VS x64 Developer PowerShell에서 다음을 확인한다. 누락되면 해당 로컬 설치 경로를 설정한 뒤 다시 확인한다. 개인 경로를 repository의 추적 파일에 기록하지 않는다.

Get-Command cl.exe, MSBuild.exe
$required_roots = 'FESA_GTEST_SOURCE_DIR','FESA_MKL_ROOT','FESA_TBB_ROOT','FESA_HDF5_ROOT','FESA_OMP_ROOT'
foreach ($root_name in $required_roots) {
  $root_path = [Environment]::GetEnvironmentVariable($root_name)
  if (-not $root_path -or -not (Test-Path -LiteralPath $root_path -PathType Container)) {
    throw "Missing local dependency root: $root_name"
  }
}

위 확인은 환경변수 방식의 준비 절차다. Fesa.Local.props를 사용하는 경우에는 그 파일의 동일 MSBuild property 값을 확인한다. CMake는 Fesa.Local.props를 읽지 않는다.

주 개발 빌드와 직접 검사

저장소 root의 VS x64 개발 환경에서 실행한다. 앞 명령이 실패하면 뒤 명령으로 진행하지 않는다.

MSBuild FESA.sln /m:2 /p:Configuration=Debug /p:Platform=x64
if ($LASTEXITCODE -ne 0) { throw 'MSBuild failed' }

출력은 .build/native/Debug다. Solver CLI는 src/fesa/fesa.exe, 세 검사 실행기는 tests/fesa_unit_tests.exe, tests/fesa_integration_tests.exe, tests/fesa_reference_tests.exe에 있다. Release는 별도의 Release 디렉터리를 사용한다. 직접 MSBuild는 CMake·Ninja·Doxygen을 선행 실행하지 않는다.

다음은 한 번의 전체 직접 검사 예시다. 각 실행기는 새 process이므로 직렬로 실행한다. 고유 디렉터리의 raw 출력·XML과 discovery를 보관한다. 이 예시는 현재 PowerShell process의 TMP/TEMP와 GoogleTest 선택 환경을 변경한다.

$verify_run = Join-Path $env:LOCALAPPDATA ('fv-' + [guid]::NewGuid().ToString('N').Substring(0,8))
New-Item -ItemType Directory -Path $verify_run -ErrorAction Stop | Out-Null
$env:TMP = $verify_run
$env:TEMP = $verify_run
foreach ($filter_name in 'GTEST_FILTER','GTEST_TOTAL_SHARDS','GTEST_SHARD_INDEX','GTEST_SHARD_STATUS_FILE','GTEST_OUTPUT') {
  Remove-Item -LiteralPath ('Env:' + $filter_name) -ErrorAction SilentlyContinue
}
foreach ($test_name in 'fesa_unit_tests','fesa_integration_tests','fesa_reference_tests') {
  $test_exe = Join-Path '.build/native/Debug/tests' ($test_name + '.exe')
  & $test_exe --gtest_list_tests > (Join-Path $verify_run ($test_name + '-discovery.txt'))
  if ($LASTEXITCODE -ne 0) { throw "Discovery failed: $test_name" }
  & $test_exe ('--gtest_output=xml:' + (Join-Path $verify_run ($test_name + '.xml'))) *> (Join-Path $verify_run ($test_name + '-raw.txt'))
  if ($LASTEXITCODE -ne 0) { throw "Tests failed: $test_name; records: $verify_run" }
}

생성된 경로에서도 실제 최장 lease 경로를 확인한다. 너무 길면 승인된 짧은 작업 위치를 사용한다.

CMake 보조 빌드

같은 VS x64 환경에서 로컬 CONFIG package 환경변수를 설정한 뒤 실행한다. 한국어 MSVC의 include 추적을 위해 configure/build의 code page를 65001로 맞춘다. 직접 검사와 별개의 짧고 고유한 TMP/TEMP를 만들고 상속된 필터·sharding을 제거한다.

Get-Command cmake.exe, ninja.exe
chcp 65001
$cmake_verify_run = Join-Path $env:LOCALAPPDATA ('fc-' + [guid]::NewGuid().ToString('N').Substring(0,8))
New-Item -ItemType Directory -Path $cmake_verify_run -ErrorAction Stop | Out-Null
$env:TMP = $cmake_verify_run
$env:TEMP = $cmake_verify_run
foreach ($filter_name in 'GTEST_FILTER','GTEST_TOTAL_SHARDS','GTEST_SHARD_INDEX','GTEST_SHARD_STATUS_FILE','GTEST_OUTPUT') {
  Remove-Item -LiteralPath ('Env:' + $filter_name) -ErrorAction SilentlyContinue
}
cmake --preset windows-msvc-ninja-debug
if ($LASTEXITCODE -ne 0) { throw 'Configure failed' }
cmake --build --preset windows-msvc-ninja-debug --parallel 2
if ($LASTEXITCODE -ne 0) { throw 'Build failed' }
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
if ($LASTEXITCODE -ne 0) { throw 'Discovery failed' }
ctest --preset windows-msvc-ninja-debug --output-on-failure -j 1
if ($LASTEXITCODE -ne 0) { throw 'CTest failed' }

Debug tree는 .build/cmake-debug, Release tree는 .build/cmake-release다. CLI는 각각의 tree에서 src/fesa/fesa.exe에 있다. Native와 CMake의 실행 기록을 분리하고 discovery가 0건이 아닌지, 전체 identity가 일치하는지 확인한다. CTest label만으로 물리 기능을 선별하지 않는다. 현재 공통 label에는 beam 이름이 들어 있으며 전체 검사의 procedure 분류가 아니다. fesa_docs는 Doxygen을 검출했을 때만 존재하는 선택적 target이다.

Python 비교기와 실제 모델

Python suite는 pytest·NumPy·h5py를 사용한다. 설치된 환경에서 다음을 실행한다.

python -c "import pytest, numpy, h5py"
if ($LASTEXITCODE -ne 0) { throw 'Python dependencies are missing' }
python -m pytest tests -q
if ($LASTEXITCODE -ne 0) { throw 'Python tests failed' }

scripts/verification/compare_hex8.py와 compare_hht_dynamic.py는 입력·reference·HDF5를 읽고 지정한 JSON report를 쓴다. Solver는 실행하지 않는다. 실행 전에 각 script의 --help로 필수 인자와 덮어쓰기 방지 조건을 확인하고 기존 report와 다른 출력 위치를 사용한다.

실제 모델은 원본 INP hash를 확인해 새 작업 디렉터리로 복사한 뒤 fesa.exe <작업복사본.inp>로 실행한다. 출력은 해당 입력의 sibling이다. Exit·로그·새 HDF5의 identity를 확인한 뒤 대응하는 정식 reference와 비교한다. reference/temp는 사용하지 않는다. 원본 폴더 안에서 solver를 실행하지 않는다.

다음은 Debug 빌드 뒤 정식 beam 입력을 새 위치에서 실행하는 예시다. 원본 폴더에 쓰지 않으며 비교 CSV는 복사·수정하지 않는다. 실행 성공은 후속 reference 비교를 대신하지 않는다.

$model_source = 'reference/cantilever beam/cantilever beam.inp'
$model_run = Join-Path $env:LOCALAPPDATA ('fm-' + [guid]::NewGuid().ToString('N').Substring(0,8))
New-Item -ItemType Directory -Path $model_run -ErrorAction Stop | Out-Null
$model_copy = Join-Path $model_run 'beam.inp'
Copy-Item -LiteralPath $model_source -Destination $model_copy -ErrorAction Stop
if ((Get-FileHash -LiteralPath $model_source).Hash -ne (Get-FileHash -LiteralPath $model_copy).Hash) {
  throw 'Input copy hash mismatch'
}
& '.build/native/Debug/src/fesa/fesa.exe' $model_copy
if ($LASTEXITCODE -ne 0) { throw "Solver failed; records: $model_run" }
Get-Item -LiteralPath (Join-Path $model_run 'beam_results.h5'), (Join-Path $model_run 'beam_log.txt')

시간 측정과 배포의 경계

성능 판정은 Ryzen 7 5800H의 Windows/MSVC x64 최적화 Release가 기준이다. 같은 thread·runtime·전원·compiler 조건에서 워밍업 없이 모델별 process를 한 번 측정한다. Process 시작 요청 직전부터 종료 직후까지 입력·계산·복구·로그·HDF5 최종화를 포함한다. 빌드·복사·VTune·비교는 측정 구간 밖이다. Debug 시간이나 반복 최솟값으로 대체하지 않는다. 배포 형식·installer·dependency 재배포 조건은 미확정이며 개발 빌드 절차를 배포 절차로 간주하지 않는다.