Научные вычисления
Scientific Computing на собеседовании
В 1996 году ракета Ariane 5 взорвалась через 39 секунд после старта - $370M убытков. Причина: 64-битное число с плавающей точкой не помещалось в 16-битное целое в коде, унаследованном от Ariane 4. В 1991 году Patriot промахнулся из-за накопления ошибки округления 0.1 в двоичном представлении - 28 убитых солдат. На собеседовании по scientific computing вопросы про conditioning, stability, выбор алгоритма - не академические упражнения, а защитный фронт против реальных катастроф. Сильный кандидат демонстрирует не знание формул, а способность связать numerical detail с системными последствиями: 'почему мы не используем нормальные уравнения для регрессии', 'когда переходить с FP32 на FP16', 'как обсуждать precision vs latency'.
- **Ariane 5 (1996)**: $370M ракета взорвалась из-за integer overflow в legacy-коде - типичный кейс numerical issue
- **Patriot Dhahran (1991)**: накопление ошибки 0.1 в binary дало 0.34 сек дрейфа за 100 часов работы, 28 смертей
- **Google TPU**: bfloat16 specifically спроектирован под ML workload - другой trade-off между range и precision против IEEE float16
- **OpenAI GPT-4 inference**: mixed FP16/INT8 quantization для развёртывания на 1M+ запросов/сек при сохранении 99% качества
- **LAPACK/MKL/OpenBLAS**: индустриальные библиотеки, оптимизированные под конкретные CPU, обогнать вручную почти невозможно
Numerical Analysis: условность и точность
В 1991 году ракета Patriot в Дахране промахнулась мимо иракской Scud, попавшей в казармы и убившей 28 солдат. Причина: системное накопление ошибки округления при умножении 0.1 в двоичном представлении. После 100 часов работы внутренние часы сдвинулись на 0.34 секунды - этого хватило, чтобы целеуказатель ушёл на 600 метров. На собеседовании вопрос 'почему `0.1 + 0.2 != 0.3`?' - точка входа в более глубокий разговор о **conditioning** задачи и **stability** алгоритма. Conditioning - свойство задачи (плохо обусловленная матрица плохо инвертируется любым алгоритмом). Stability - свойство алгоритма (метод Гаусса с pivoting устойчив, без - не всегда). Грамотный кандидат различает эти понятия и не путает источник ошибки.
Condition number матрицы κ(A) = ‖A‖ * ‖A^-1‖. Если κ = 10^6, то относительная ошибка ввода 10^-7 (порядок машинного эпсилон single precision) даёт относительную ошибку выхода до 10^-1. На double precision (eps ~ 10^-16) можно работать с κ до 10^10. Beyond - нужно reformulate задачу: SVD с truncation, LSQR вместо normal equations, scaling. Numerical analysis на интервью - не про знание формул, а про умение читать диагностики (residual, condition estimate) и предлагать reformulation.
Кандидат на интервью говорит: 'Условный номер матрицы 10^14 - значит алгоритм нестабильный'. Что не так с этой формулировкой?
Algorithm Design: выбор метода под характер задачи
Интервьюер: 'Решите Ax=b, A - матрица 10^6 x 10^6'. Слабый кандидат предлагает `np.linalg.solve` (O(n^3)) и кладёт интервью. Сильный кандидат задаёт уточняющие вопросы: sparse? structured? symmetric positive definite? Сколько раз решать с разными b? Какая точность нужна? Каждый ответ переключает алгоритм: dense LU - O(n^3) и 8 TB памяти, неприменим. Sparse direct (CHOLMOD) - O(n * nnz^2) если есть структура. Iterative (CG для SPD, GMRES общий) - O(k * nnz), k - число итераций ~ sqrt(κ). Preconditioner (ILU, multigrid) - радикальное ускорение. Без диалога нет правильного ответа - это и проверяется.
Дерево выбора метода на интервью: (1) **Размер**: <10^4 - dense LU/QR; <10^7 sparse - direct solver; >10^7 - iterative. (2) **Структура**: symmetric? positive definite? Toeplitz/circulant (FFT)? banded? block structure? (3) **Использование**: single solve - direct; same A, many b - factorize once, reuse; varying A - iterative с warm start. (4) **Hardware**: CPU - BLAS3 для dense; GPU - batched ops; distributed - block algorithms. Кандидат, начинающий с уточняющих вопросов, набирает больше очков, чем тот, кто сразу пишет код.
Анти-паттерны интервью: (а) сразу писать код без вопросов; (б) предлагать `np.linalg.inv(A) @ b` вместо `solve` - инверсия в 3x медленнее и менее устойчива; (в) игнорировать структуру и применять dense метод; (г) забывать про preconditioner для iterative methods на ill-conditioned системах.
Интервьюер: 'У вас матрица A 5000x5000, и нужно решить Ax=b для 1000 разных b с тем же A. Что предложите?'
Optimization: BLAS, vectorization и parallelism
Кандидат написал numerical loop на Python и хвалится результатом - 100 GFLOPS на матричном произведении. Интервьюер достаёт ноутбук, запускает `numpy.dot` на той же машине: 500 GFLOPS. Разница - в BLAS. **BLAS Level 1** (vector ops) - 1 op на 2 memory accesses, memory-bound. **Level 2** (matrix-vector) - 2 ops на 1.5 memory, всё ещё memory-bound. **Level 3** (matrix-matrix) - O(n^3) ops на O(n^2) memory, compute-bound, можно достичь peak FLOPS. Хороший candidate знает, что вычисления должны быть переформулированы в Level 3, чтобы амортизировать memory bandwidth. NumPy/SciPy под капотом дёргают MKL/OpenBLAS, который уже сделал всю работу.
Roofline model - инструмент анализа на интервью: ось X - arithmetic intensity (FLOP/byte), ось Y - performance (FLOPS). Линия 'roof' = min(peak_FLOPS, bandwidth * intensity). Algorithm с intensity ниже break-even point - memory-bound, выше - compute-bound. AXPY (Level 1) intensity 1/4 - memory-bound. GEMM (Level 3) intensity n/3 - compute-bound при больших n. Vectorization (SIMD AVX-512) даёт 8x speedup на double, multi-threading - ещё 16-64x на современных CPU. GPU - 10-100x сверх этого для compute-bound кодов.
На интервью спрашивают: 'У вас цикл по 10^9 элементам с независимыми вычислениями над каждым. Достаточно использовать `multiprocessing.Pool`?'
Tradeoffs: точность vs скорость, память vs вычисления
Интервьюер: 'Постройте систему для inference нейросети 10B параметров на 1000 запросов/секунду'. Senior кандидат озвучивает trade-offs: **FP16 vs FP32** - 2x скорость и 2x память, но потеря точности 0.5% на типичных моделях. **INT8 quantization** - ещё 4x ускорение, потеря 1-2%, требует calibration. **Sparsity** - 2:4 structured sparsity на A100/H100 даёт 2x ускорение matmul при 50% параметров. **Distillation** - модель в 10x меньше с 95% точности оригинала. Каждый trade-off - не 'хорошо/плохо', а конкретная позиция на кривой производительности vs качества. Кандидат, способный обсудить эти точки, демонстрирует архитектурное мышление.
Универсальный паттерн tradeoff на интервью: (1) **memory vs compute** - recomputation vs caching (FFT recompute, gradient checkpointing); (2) **precision vs speed** - mixed precision training (FP16 forward, FP32 master weights); (3) **accuracy vs latency** - approximate algorithms (Locality Sensitive Hashing для nearest neighbor); (4) **throughput vs latency** - batching (latency растёт, throughput тоже); (5) **complexity vs maintainability** - cuBLAS vs hand-tuned CUDA. Senior кандидат не выбирает 'лучшее', а оценивает позицию на Pareto frontier для конкретного use case.
Numerical code - это про знание формул и BLAS API
Numerical code на собеседовании - это про умение читать и обсуждать trade-offs: conditioning vs stability, dense vs sparse, direct vs iterative, FP32 vs FP16, memory vs compute. Кандидат, знающий 50 формул, но не видящий их связи с системой, проигрывает кандидату, который начинает с уточняющих вопросов и обсуждает альтернативы
Senior уровень в HPC/numerical - это умение синтезировать решение из ограничений (память, время, точность, hardware), а не цитировать учебник. Современные библиотеки (NumPy, SciPy, PyTorch, JAX) скрывают детали реализации - важнее понимать, какой API когда использовать и почему. Интервьюер ищет именно systems thinking, не numerical knowledge.
Интервьюер: 'Ваше приложение - real-time inference с budget 50ms. Модель работает 100ms на FP32. Что выбрать?'
Ключевые идеи
- **Conditioning vs stability** - терминологическое различие на интервью: conditioning принадлежит задаче (κ(A)), stability принадлежит алгоритму
- **Выбор метода** начинается с уточняющих вопросов: размер, структура, частота использования, hardware; ответ зависит от ответов
- **BLAS Level 3** компенсирует memory bandwidth - переформулировать вычисление в matmul-форму = главная оптимизация для scientific code
- **Trade-offs** на собеседовании: FP32/FP16/INT8/INT4, dense/sparse, direct/iterative, recompute/cache; senior кандидат обсуждает Pareto frontier, а не выбирает 'лучшее'
- **Numerical interview** - не про формулы, а про systems thinking: связь между numerical detail и системными последствиями (стоимость, latency, accuracy, certification)
Связанные темы
Scientific Computing на интервью пересекается с HPC, ML deployment и системным дизайном:
- Scientific Computing на масштабе — Cloud HPC, reproducibility, workflow - продакшен-следствия трейд-оффов, обсуждаемых на интервью
- Numerical Optimization — Gradient descent, Newton, L-BFGS - семейство алгоритмов с trade-offs convergence rate vs memory
- Параллельные вычисления для науки — BLAS Level 3 + multi-threading + GPU - стек оптимизации, на котором держится современный numerical code
Вопросы для размышления
- Patriot и Ariane показывают, что numerical bug может стоить жизней и миллиардов. Какие процессы verification могут предотвратить такие классы ошибок в современном production-коде?
- На интервью senior-инженер обсуждает trade-offs вместо ответа 'правильным методом'. Какие еще области CS требуют такого мышления, и где наоборот ожидается прямой ответ?
- Mixed precision training (FP16+FP32 master) - архитектурное решение, скрывающее сложность от пользователя. Какие ещё пары precision могут быть полезны (например, INT8 inference с FP32 калибровкой)?
Связанные уроки
- sci-13 — Собеседование по HPC строится на знании масштабирования
- alg-01-big-o — Сложность алгоритмов - базовый вопрос на HPC интервью
- par-06 — MPI - стандартный вопрос на научные вычисления
- opt-16 — Оба урока - interview prep форматы для смежных областей
- dl-12 — HPC interviewer часто спрашивают про distributed deep learning
- nm-01