From 171c8d5489d5a9cc031901cadc79923f149dc9ff Mon Sep 17 00:00:00 2001 From: Rorik Star Platinum Date: Sun, 30 Nov 2025 01:06:36 +0300 Subject: [PATCH] today's savings --- 10-linux/00-utils/helix/fill match arms.md | 26 +++++ 10-linux/30-computer-arch/GPU CPU.md | 50 ++++++++++ .../00-rust/functional examples/Untitled.md | 56 +++++++++++ 20-dev/00-rust/iterators/it.md | 98 +++++++++++++++++++ lifestyle?/phylosophy.md | 7 ++ 5 files changed, 237 insertions(+) create mode 100644 10-linux/00-utils/helix/fill match arms.md create mode 100644 10-linux/30-computer-arch/GPU CPU.md create mode 100644 20-dev/00-rust/functional examples/Untitled.md create mode 100644 20-dev/00-rust/iterators/it.md create mode 100644 lifestyle?/phylosophy.md diff --git a/10-linux/00-utils/helix/fill match arms.md b/10-linux/00-utils/helix/fill match arms.md new file mode 100644 index 0000000..57fb515 --- /dev/null +++ b/10-linux/00-utils/helix/fill match arms.md @@ -0,0 +1,26 @@ +В **Helix** пока нет встроенной полноценной поддержки сниппетов в том виде, как это сделано в VS Code (где нажал Tab и развернулся шаблон кода), но есть очень мощная альтернатива через **LSP (Language Server Protocol)**. + +То, что ты описываешь ("заполнить match по всем вариантам enum"), — это фича **rust-analyzer**, и она работает в Helix через **Code Actions**. + +### Как сделать "Fill match arms" в Helix: + +1. Напиши `match s.split_once(',') {}`. +2. Поставь курсор **внутри** фигурных скобок `{}` или на ключевое слово `match`. +3. Нажми **`Space` + `a`** (команда `code_action`). +4. В появившемся меню выбери **"Fill match arms"**. + +Rust-analyzer автоматически сгенерирует код: +```rust +match s.split_once(',') { + Some(_) => todo!(), + None => todo!(), +} +``` + +### Насчет классических сниппетов +В Helix нативная поддержка сниппетов (как в VSCode: набрал `for` -> Tab -> развернулся цикл) находится в разработке/планах. +Сейчас сообщество использует: +1. **Внешние решения:** Например, через автодополнение LSP, если сервер их поддерживает (rust-analyzer кое-что умеет, например `tmod` разворачивает тестовый модуль). +2. **Скрипты/Пайпы:** Можно настроить хоткеи на вставку текста через `pipe` из внешних файлов, но это костыльно. + +Так что для Rust твой лучший друг — это `Space` + `a` (Code Actions). Это даже круче сниппетов, потому что оно контекстно-зависимое. \ No newline at end of file diff --git a/10-linux/30-computer-arch/GPU CPU.md b/10-linux/30-computer-arch/GPU CPU.md new file mode 100644 index 0000000..43df49e --- /dev/null +++ b/10-linux/30-computer-arch/GPU CPU.md @@ -0,0 +1,50 @@ +Ты абсолютно прав насчет того, что GPU — это "много слабых процессоров", но твои догадки про отсутствие кэша и памяти не совсем верны. Давай разберем "кишочки" архитектурно, используя правильные термины. + +Главное отличие можно описать одной фразой: **CPU оптимизирован под Latency (задержку), а GPU — под Throughput (пропускную способность).** + +### 1. Архитектура кристалла (Die Layout) +Если посмотреть на фото кристалла под микроскопом, разница бросается в глаза: + +* **CPU:** Огромную часть площади занимает **Control Unit** (блок управления) и **Кэш** (L1/L2/L3). Сами вычислительные блоки (**ALU** — Arithmetic Logic Unit) занимают меньшую часть места. + * *Зачем:* CPU — это менеджер-бюрократ. Его задача — выполнять сложные, запутанные инструкции, где много условий `if/else`. Он тратит миллиарды транзисторов на **Branch Prediction** (предсказание ветвлений) и **Out-of-Order Execution** (внеочередное исполнение), чтобы угадать, какую инструкцию ты захочешь выполнить следующей, пока текущая еще считается.[3][5] +* **GPU:** Почти весь кристалл забит тысячами мелких **ALU**. Control Unit крошечный и тупой. + * *Зачем:* GPU — это армия рабочих. Им не нужно гадать. Им дают команду: "Умножь эти 10 миллионов чисел на 2". Им не нужен сложный менеджмент, им нужна грубая сила.[1] + +### 2. SIMD и "Проблема ветвлений" +Это, пожалуй, самое главное "кишечное" отличие. + +* **CPU (SISD/MIMD):** Каждое ядро может делать что-то свое. Одно ядро играет музыку, другое считает физику. +* **GPU (SIMT - Single Instruction, Multiple Threads):** + Ядра GPU сгруппированы в "пачки" (у NVIDIA это называется **Warp**, обычно 32 потока). + * **Как это работает:** Блок управления посылает **одну** инструкцию сразу на 32 ядра. Все 32 ядра *обязаны* сделать одно и то же действие, но с разными данными. + * **Где GPU умирает:** Если ты напишешь код с условием `if (x > 0) { do_A() } else { do_B() }`, и внутри одного варпа у половины потоков `x > 0`, а у другой нет, происходит **Warp Divergence**. Сначала половина ядер делает `do_A`, пока вторая половина *простаивает и ждет*, а потом наоборот. Производительность падает в разы. CPU такие ветвления щелкает как орешки.[6][3] + +### 3. Миф про память и кэш +Твое предположение, что у GPU нет кэша и он не работает с памятью — **неверно**. + +* **Память (VRAM):** У GPU есть свой контроллер памяти, и он *намного* мощнее, чем у CPU. + * Шина данных CPU: узкая (64-128 бит), но с низкой задержкой. + * Шина данных GPU: огромная (128-384 бит и более, память GDDR6X). Это широченная труба. GPU может прокачивать терабайты данных в секунду. +* **Кэш:** У GPU есть кэши L1 и L2, и даже Shared Memory (управляемый вручную кэш). Просто они работают иначе. Они нужны не для того, чтобы хранить данные долго (как у CPU), а чтобы "склеивать" (coalescing) запросы. Если 32 потока просят 32 соседних байта из памяти, GPU объединит их в один запрос. Если они просят данные вразнобой — GPU "захлебнется".[5][6] + +### 4. Ответ на Rust-часть: "Графический инжиниринг" +Ты правильно уловил суть. Когда ты пишешь на Rust под GPU (будь то `wgpu` для графики или `burn`/`candle` для ML), ты занимаешься **оркестрацией**: + +1. **Host Code (CPU/Rust):** Ты подготавливаешь данные, загружаешь текстуры/веса в VRAM (через шину PCIe) и формируешь **Command Buffer** (список команд). +2. **Device Code (Shader/Kernel):** Ты пишешь (или библиотека генерирует) маленькие программы (шейдеры на WGSL/GLSL или ядра CUDA), которые загружаются на GPU. +3. **Dispatch:** Ты с CPU пинаешь GPU: "Выполни вот этот шейдер 1 миллион раз". + +Твое взаимодействие "напрямую с видеокартой" заключается в правильном управлении памятью и создании таких структур данных, чтобы тысячи глупых ядер GPU могли читать их линейно, не прыгая по памяти (иначе потеряешь всю мощь). + +**Итог:** GPU — это не просто много слабых CPU. Это архитектура, где пожертвовали *управлением* и *логикой* ради *математической плотности* и *ширины канала памяти*. + +[1](https://aws.amazon.com/ru/compare/the-difference-between-gpus-cpus/) +[2](https://timeweb.cloud/blog/gpu-i-cpu-v-chem-raznica) +[3](https://habr.com/ru/companies/otus/articles/844260/) +[4](https://tproger.ru/articles/gpu-protiv-cpu--chto-nuzhno-znat-dlya-raboty-s-ii-v-2025) +[5](https://www.cloud4y.ru/blog/cpu-gpu-what-is-the-difference/) +[6](https://www.ittelo.ru/news/cpu-i-gpu-v-chem-raznitsa/) +[7](https://oblakoru.ru/blogs/cpu-i-gpu-v-chem-raznicza-i-chto-vybrat/) +[8](https://www.fastvideo.ru/blog/cpu-vs-gpu-fast-image-processing.htm) +[9](https://mws.ru/blog/cpu-i-gpu-v-chem-otlichie/) +[10](https://www.youtube.com/watch?v=R_9B_DCe1-E) \ No newline at end of file diff --git a/20-dev/00-rust/functional examples/Untitled.md b/20-dev/00-rust/functional examples/Untitled.md new file mode 100644 index 0000000..cea208d --- /dev/null +++ b/20-dev/00-rust/functional examples/Untitled.md @@ -0,0 +1,56 @@ +```rust +#[derive(Debug)] +struct Person { + name: String, + age: u8, +} + +impl Default for Person { + fn default() -> Self { + Self { + name: String::from("John"), + age: 30, + } + } +} +``` + +```rust +impl From<&str> for Person { + fn from(s: &str) -> Self { + s.split_once(',') + .filter(|(name, _)| !name.is_empty()) + .and_then(|(name, age_str)| { + age_str.parse::().ok().map(|age| (name, age)) + }) + .map(|(name, age)| Person { + name: name.to_string(), + age, + }) + .unwrap_or_default() + } +} +``` + +как это написать через match: + +```rust +impl From<&str> for Person { + fn from(s: &str) -> Self { + let Some((name, age_str)) = s.split_once(',') else { + return Person::default(); + }; + if name.is_empty() { + return Person::default(); + } + let Ok(age) = age_str.parse::() else { + return Person::default(); + }; + Person { + name: name.to_string(), + age, + } + } +} +``` + diff --git a/20-dev/00-rust/iterators/it.md b/20-dev/00-rust/iterators/it.md new file mode 100644 index 0000000..3c4827d --- /dev/null +++ b/20-dev/00-rust/iterators/it.md @@ -0,0 +1,98 @@ +Ты абсолютно прав! Rust ощущается как "Lego Technic": детали (типы, трейты) либо идеально защелкиваются (type check passed), либо ты физически не можешь их соединить. В C++ часто можно "насильно" прикрутить деталь изолентой (reinterpret_cast), и она отвалится на ходу. + +### 1. Как создавать методы для функциональных цепочек? + +Да, ты можешь писать методы, которые "чейнятся" (chaining). Секрет в том, что метод должен: +1. Принимать `self` (по значению) — это называется **builder pattern** или **consuming builder**. +2. Возвращать `Self`. + +```rust +struct Config { + port: u16, + debug: bool, +} + +impl Config { + fn new() -> Self { + Self { port: 80, debug: false } + } + + // Принимает 'mut self', меняет его и возвращает 'Self' + fn set_port(mut self, port: u16) -> Self { + self.port = port; + self // Возвращаем измененный объект дальше по конвейеру + } + + fn enable_debug(mut self) -> Self { + self.debug = true; + self + } +} + +fn main() { + // Функциональная цепочка! + let conf = Config::new() + .set_port(8080) + .enable_debug(); +} +``` +Если ты про цепочки типа `.map().filter()`, то там возвращается не `Self`, а новый тип-обертка (например, `Map`), который реализует тот же трейт `Iterator`. + +*** + +### 2. Как работает магия `collect()`? + +`collect()` — это, пожалуй, самый "волшебный" метод в Rust. Он умеет превращать итератор во **что угодно**, что реализует трейт `FromIterator`. + +#### Сигнатура collect (упрощенно) +```rust +fn collect(self) -> B +where + B: FromIterator; +``` +Он говорит: "Я могу стать типом `B`, если тип `B` умеет создавать себя из моих элементов". + +#### Как это работает внутри? +Когда ты пишешь: +```rust +let vec: Vec = iter.collect(); +``` +1. Rust видит, что ты хочешь получить `Vec`. +2. Он ищет реализацию `impl FromIterator for Vec`. +3. В этой реализации (в стандартной библиотеке) написано примерно следующее: + +```rust +// Псевдокод реализации внутри std +impl FromIterator for Vec { + fn from_iter>(iter: I) -> Self { + let mut vec = Vec::new(); + for item in iter { + vec.push(item); + } + vec + } +} +``` +То есть `collect` просто делегирует работу методу `from_iter` целевого типа. + +#### Почему это круто? +Ты можешь реализовать `FromIterator` для **своей структуры**, и `collect` начнет работать для неё автоматически! + +```rust +struct MyCollection(Vec); + +// Учим нашу коллекцию создаваться из итератора +impl FromIterator for MyCollection { + fn from_iter>(iter: T) -> Self { + let mut c = MyCollection(Vec::new()); + for i in iter { + c.0.push(i); + } + c + } +} + +fn main() { + let my_col: MyCollection = vec![1, 2, 3].into_iter().collect(); // Работает! +} +``` \ No newline at end of file diff --git a/lifestyle?/phylosophy.md b/lifestyle?/phylosophy.md new file mode 100644 index 0000000..763f4b9 --- /dev/null +++ b/lifestyle?/phylosophy.md @@ -0,0 +1,7 @@ +| Philosopher | Concept | Connection to You | +| ------------ | --------------------- | ------------------------------------------------------------------------------ | +| John Dewey | Experimentalism | Life is not aboutbeingstable, butdoingexperiments to solve problems. | +| Heraclitus | Flux (Panta Rhei) | Stability is a lie; conflict/change is the only reality. | +| Nietzsche | Will to Power | Despising the "comfort" of stability; creating the future through strength. | +| Nassim Taleb | Antifragility | "Stability" creates hidden risks; volatility/experimentation creates strength. | +| Karl Popper | Piecemeal Engineering | Progress comes from small, correctable experiments, not grand stable plans. |