Спойлер для экономии времени читающих — я просто скачаю DeepSeek и запущу его через llama.cpp, на какую-либо научную новизну этот пост совершенно не претендует. Зачем это на хабре, если там всего одна команда? Просто в комментариях к посту «Мануал по запуску полной модели DeepSeek-R1 локально» я спросил «имеет ли смысл попробовать на том железе, что у меня есть», и меня попросили это сделать, ну и некоторое количество «плюсиков» говорит о том, что кому-нибудь это будет интересно, ну а раз паззл сложился — о том и пост, просто развёрнутое продолжение, алаверды, так сказать, к предыдущему оратору. И да, я абсолютный дилетант в LLM, это первая «пристрелка», так что «туториалом» оформлять пост не буду, там могут быть неточности. Если кому интересны подробности — можно продолжить чтение.
Второй спойлер — да, это работает. Но очень медленно. Но работает.
Железо
Упражняться я буду вот на такой конфигурации:
HP z8 G4 рабочая станция примерно пятилетней давности в практически стоковом варианте.
Два процессора Xeon Gold 6132, 768 GB памяти DDR4, терабайтный NVMe SSD Samsung.
.
CPU-z выдаёт мне 10000+ попугаев:
Память набрана плашками по 64 ГБ, их там двенадцать штук:
Бенчмарк памяти и кэша я уже в комментах показывал, вынесу сюда тоже:
Видеокарт там две — NVidia Quadro K4200 да AMD Radeon Pro WX 9100, но использоваться как GPU они не будут (смысла в общем нет).
Диск:
Вообще их там четыре таких, но в рейд объединять не буду, модель один раз грузится в память, в принципе и так норм.
Комп остался как тестовый от одного проекта, в котором надо было быстро обрабатывать полтерабайта картинок, прилетающих от нескольких скоростных камер, теперь просто пылится под столом и эпизодически используется для упражнений.
Скачиваем DeepSeek
Я бы мог просто написать «скачайте DeepSeek R1 Q8_0», но тут есть небольшой нюанс. Дело в том, что на работе у меня все искусственные интеллекты старательно заблокированы злым админом, охраняющим интеллектуальную собственность. У меня нет онлайн доступа ни к ChatGPT, ни к Perplexity, ни к DeepSeek, равно как все дропбоксы, гуглодрайвы, онлайн заметочники — блокировано решительно всё. Причём не только на уровне прокси, но также фактически осуществляется MITM подменой сертификатов, поэтому скачать с Hugging Face/Unsloth AI я ничего не могу, получая отлуп 500. Издержки работы в большой компании. Обходить защиты — чревато, ибо Большой Брат неустанно бдит, так что качать я буду дома. А дома у меня всего-навсего 100 Мбит (хоть и оптоволокно), так что процесс не быстрый (планируйте как минимум сутки).
Поскольку репозиторий содержит несколько моделей, то я решил, что я самый умный, и слегка погуглив нашёл способ выдернуть через гит отдельную папку, а не всю репу.
Вот как-то так это делается через sparse-checkout:
git clone -n --depth=1 --filter=tree:0 https://huggingface.co/unsloth/DeepSeek-R1-GGUF
cd DeepSeek-R1-GGUF
git sparse-checkout set --no-cone /DeepSeek-R1-Q8_0
git checkout
Я включил старый комп с файлопомойкой, проверил там свободное место, выполнил команды выше, убедился, что информация пошла по проводам, и пошёл спать. Наутро я обнаружил, что туда прилетели обновления и он перезагрузился. Ну, бывает, я и забыл, что незадолго до этого поставил туда свежую Windows да не настроил как следует.
Лирическое отступление — если вы хотите временно отказаться от обновлений и возможных сопутствующих перезагрузок, то просто включите Metered connection (по-немецки Getaktete Verbindung) для сетевого адаптера, это самый наипростейший способ достичь бесконечного аптайма на компе, постоянно воткнутом в интернет.
Я это сделал, и выполнив команды второй раз, обнаружил, что «докачки» там нет и в помине, git начал качать с нуля (это видно в lfs кэше, там сначала файлы складываются во временную папку). Тут я вспомнил, что у меня валяется древний QNAP NAS, там есть качалка, но тут меня ждала другая засада — раз в сутки провайдер сбрасывает соединение, при этом NAS на это нервно реагировал, вываливал ошибку и начинал скачку снова. С торрентами он худо-бедно справлялся, а вот с https — нет. Я уже хотел было отказаться от затеи, но вы же понимаете — если я во всеуслышание напишу вот прямо здесь, что не смог скачать семьсот гиг, то надо мной будет ржать весь хабр, и я буду подвергнут публичному остракизму, так что пришлось расчехлить менеджер закачек, которым я не пользовался уже много лет.
Я это всё к тому, что если захотите скачать на слабом канале — заранее проверьте, что вы можете уверенно докачивать при обрыве соединения.
Ладно, хватит длинного вступления, короче — вот репозиторий DeepSeek-R1-GGUF, вот модель DeepSeek-R1-Q8_0, а под спойлером — прямые ссылки на список файлов, которые можно скормить любому менеджеру, я пользовался JDownloader 2.
DeepSeek-R1.Q8_0-000??-of-00015.gguf
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00001-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00002-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00003-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00004-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00005-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00006-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00007-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00008-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00009-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00010-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00011-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00012-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00013-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00014-of-00015.gguf?download=true
https://huggingface.co/unsloth/DeepSeek-R1-GGUF/resolve/main/DeepSeek-R1-Q8_0/DeepSeek-R1.Q8_0-00015-of-00015.gguf?download=true
Плюс использования менеджера ещё и в том, что днём я могу уменьшить скорость, чтобы не доставлять неудобств домашним, а ночью «открывать кран» на всю катушку.
Пока идёт скачивание, чтоб было не скучно — могу предложить загадку, как раз про это.
Во второй половине девяностых, мы, новоиспечённые выпускники физтеха, порой собирались вместе, распивали крепкие спиртные напитки и иногда смотрели фильмы на видеокассетах. В числе наиболее популярных был фильм, который мы, подрабатывающие программистами, ласково называли не иначе как «это наше кино, про эти, про ГИГАБАЙТЫ!» Угадайте, о каком фильме, выпущенном в середине девяностых, шла речь? Потом спросим у DeepSeek.
Как бы то ни было, через пару дней и ночей на терабайтном диске у меня лежали пятнадцать заветных GGUF файлов. Бережно неся их на работу, испытал странное ощущение — это что же, у меня в руках почти вся взвешенная квинтэссенция знаний человечества?! Мда...
Запускаем.
Вообще говоря существует несколько способов «запустить» DeepSeek локально — LM Studio, Ollama, llama.cpp и OpenVINO, часть из них я почерпнул из комментов, за что спасибо. Я попробовал навскидку все, но без фанатизма.
Самый наипростейший, вероятно — LM Studio. Актуальная версия на момент написания поста — 0.3.9. Я попробовал поставить дома, всё без проблем, как демка скачивается простенькая DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf на четыре с половиной гига, что позволяет запустить это дело даже на моём древнем ноуте (32 ГБ, проц. i7-4940MX). Я попробовал — даже работает, но очень медленно. Файлы моделей по умолчанию лежат в %USERPROFILE%\.lmstudio\models\lmstudio-community, там они в поддиректориях типа \DeepSeek-R1-Distill-Qwen-7B-GGUF.
Я закинул на диск инсталлятор, но вот на hp z8 прилетела и уселась птичка обломинго — «тестовая» Qwen 7B хоть и загружалась, но вываливалась в «неизвестную ошибку» после первого же промпта, а с таким трудом выкачанная Q8_0 отказалась загружаться вовсе, сославшись на нехватку ресурсов (выгрузку в GPU я отключил, не помогло). Дальше я мучить её пока не стал и отложил красивую игрушку в сторону.
Ollama в основном рассчитана на то, что скачивать модель вы будете через неё же (что невозможно в моём случае, а перекачивать дома всё ещё раз — тут уж извините),
Welcome to Ollama!
Run your first model:
ollama run llama3.2
PS C:\Windows\System32> ollama run deepseek-r1:1.5b
pulling manifest
pulling aabd4debf0c8... 100% ▕████████████████████████████████▏ 1.1 GB
pulling 369ca498f347... 100% ▕████████████████████████████████▏ 387 B
pulling 6e4c38e1172f... 100% ▕████████████████████████████████▏ 1.1 KB
verifying sha256 digest, writing manifest, success
>>> hi!
<think>
</think>
Hello! How can I assist you today? ?
так то оно работает, а вот как «подоткнуть» ей уже заранее скачанные файлы GGUF — тут чуть сложнее. То есть место-то где они должны лежать, я знаю: %USERPROFILE%\.ollama\models, но там модель надо кидать в папку \blobs, при этом переименовать файл в sha256-<хеш>, кроме того, надо добавить конфигурационный файл в \manifests\registry\.ollama.ai\library\deepseek-r1, в общем тут надо «приготовить» модель через
"ollama create DeepSeekR1 -f DeepSeek-R1.gguf", но перед этим вам придётся смержить все пятнадцать файлов вместе через "gguf-split --merge DeepSeek-R1.Q8_0-00001-of-00015.gguf DeepSeek-R1.gguf", и в общем ну его в топку такие упражнения.
А вот с llama.cpp всё получилось, и очень просто. Я было приготовился долго и нудно собирать это дело из исходников, но делать это не надо, там есть готовые сборки под Windows. Поскольку у меня железка на Xeon с поддержкой AVX512, вот эту версию я и скачал для начала.
Короче, тупо забрасываем файлы модели и содержимое архива с утилитами в одну папку (да прямо в корень диска F:\ в моём случае)
И запускаем
llama-cli.exe -m DeepSeek-R1.Q8_0-00001-of-00015.gguf -p "Hi!" -n 4096
Всё.
Все параметры командной строки (на английском, под спойлером). их там овердофига:
llama-cli.exe -h
example usage:
text generation: llama-cli.exe -m your_model.gguf -p "Hi!" -n 128
chat (conversation): llama-cli.exe -m your_model.gguf -p "Hello!" -cnv
----- common params -----
-h, --help, --usage print usage and exit
--version show version and build info
--verbose-prompt print a verbose prompt before generation (default: false)
-t, --threads N number of threads to use during generation (default: -1)
(env: LLAMA_ARG_THREADS)
-tb, --threads-batch N number of threads to use during batch and prompt processing (default:
same as --threads)
-C, --cpu-mask M CPU affinity mask: arbitrarily long hex. Complements cpu-range
(default: "")
-Cr, --cpu-range lo-hi range of CPUs for affinity. Complements --cpu-mask
--cpu-strict <0|1> use strict CPU placement (default: 0)
--prio N set process/thread priority : 0-normal, 1-medium, 2-high, 3-realtime
(default: 0)
--poll <0...100> use polling level to wait for work (0 - no polling, default: 50)
-Cb, --cpu-mask-batch M CPU affinity mask: arbitrarily long hex. Complements cpu-range-batch
(default: same as --cpu-mask)
-Crb, --cpu-range-batch lo-hi ranges of CPUs for affinity. Complements --cpu-mask-batch
--cpu-strict-batch <0|1> use strict CPU placement (default: same as --cpu-strict)
--prio-batch N set process/thread priority : 0-normal, 1-medium, 2-high, 3-realtime
(default: 0)
--poll-batch <0|1> use polling to wait for work (default: same as --poll)
-c, --ctx-size N size of the prompt context (default: 4096, 0 = loaded from model)
(env: LLAMA_ARG_CTX_SIZE)
-n, --predict, --n-predict N number of tokens to predict (default: -1, -1 = infinity, -2 = until
context filled)
(env: LLAMA_ARG_N_PREDICT)
-b, --batch-size N logical maximum batch size (default: 2048)
(env: LLAMA_ARG_BATCH)
-ub, --ubatch-size N physical maximum batch size (default: 512)
(env: LLAMA_ARG_UBATCH)
--keep N number of tokens to keep from the initial prompt (default: 0, -1 =
all)
-fa, --flash-attn enable Flash Attention (default: disabled)
(env: LLAMA_ARG_FLASH_ATTN)
-p, --prompt PROMPT prompt to start generation with
if -cnv is set, this will be used as system prompt
--no-perf disable internal libllama performance timings (default: false)
(env: LLAMA_ARG_NO_PERF)
-f, --file FNAME a file containing the prompt (default: none)
-bf, --binary-file FNAME binary file containing the prompt (default: none)
-e, --escape process escapes sequences (\n, \r, \t, \', \", \\) (default: true)
--no-escape do not process escape sequences
--rope-scaling {none,linear,yarn} RoPE frequency scaling method, defaults to linear unless specified by
the model
(env: LLAMA_ARG_ROPE_SCALING_TYPE)
--rope-scale N RoPE context scaling factor, expands context by a factor of N
(env: LLAMA_ARG_ROPE_SCALE)
--rope-freq-base N RoPE base frequency, used by NTK-aware scaling (default: loaded from
model)
(env: LLAMA_ARG_ROPE_FREQ_BASE)
--rope-freq-scale N RoPE frequency scaling factor, expands context by a factor of 1/N
(env: LLAMA_ARG_ROPE_FREQ_SCALE)
--yarn-orig-ctx N YaRN: original context size of model (default: 0 = model training
context size)
(env: LLAMA_ARG_YARN_ORIG_CTX)
--yarn-ext-factor N YaRN: extrapolation mix factor (default: -1.0, 0.0 = full
interpolation)
(env: LLAMA_ARG_YARN_EXT_FACTOR)
--yarn-attn-factor N YaRN: scale sqrt(t) or attention magnitude (default: 1.0)
(env: LLAMA_ARG_YARN_ATTN_FACTOR)
--yarn-beta-slow N YaRN: high correction dim or alpha (default: 1.0)
(env: LLAMA_ARG_YARN_BETA_SLOW)
--yarn-beta-fast N YaRN: low correction dim or beta (default: 32.0)
(env: LLAMA_ARG_YARN_BETA_FAST)
-dkvc, --dump-kv-cache verbose print of the KV cache
-nkvo, --no-kv-offload disable KV offload
(env: LLAMA_ARG_NO_KV_OFFLOAD)
-ctk, --cache-type-k TYPE KV cache data type for K
allowed values: f32, f16, bf16, q8_0, q4_0, q4_1, iq4_nl, q5_0, q5_1
(default: f16)
(env: LLAMA_ARG_CACHE_TYPE_K)
-ctv, --cache-type-v TYPE KV cache data type for V
allowed values: f32, f16, bf16, q8_0, q4_0, q4_1, iq4_nl, q5_0, q5_1
(default: f16)
(env: LLAMA_ARG_CACHE_TYPE_V)
-dt, --defrag-thold N KV cache defragmentation threshold (default: 0.1, < 0 - disabled)
(env: LLAMA_ARG_DEFRAG_THOLD)
-np, --parallel N number of parallel sequences to decode (default: 1)
(env: LLAMA_ARG_N_PARALLEL)
--rpc SERVERS comma separated list of RPC servers
(env: LLAMA_ARG_RPC)
--mlock force system to keep model in RAM rather than swapping or compressing
(env: LLAMA_ARG_MLOCK)
--no-mmap do not memory-map model (slower load but may reduce pageouts if not
using mlock)
(env: LLAMA_ARG_NO_MMAP)
--numa TYPE attempt optimizations that help on some NUMA systems
- distribute: spread execution evenly over all nodes
- isolate: only spawn threads on CPUs on the node that execution
started on
- numactl: use the CPU map provided by numactl
if run without this previously, it is recommended to drop the system
page cache before using this
see https://github.com/ggerganov/llama.cpp/issues/1437
(env: LLAMA_ARG_NUMA)
-dev, --device <dev1,dev2,..> comma-separated list of devices to use for offloading (none = don't
offload)
use --list-devices to see a list of available devices
(env: LLAMA_ARG_DEVICE)
--list-devices print list of available devices and exit
-ngl, --gpu-layers, --n-gpu-layers N number of layers to store in VRAM
(env: LLAMA_ARG_N_GPU_LAYERS)
-sm, --split-mode {none,layer,row} how to split the model across multiple GPUs, one of:
- none: use one GPU only
- layer (default): split layers and KV across GPUs
- row: split rows across GPUs
(env: LLAMA_ARG_SPLIT_MODE)
-ts, --tensor-split N0,N1,N2,... fraction of the model to offload to each GPU, comma-separated list of
proportions, e.g. 3,1
(env: LLAMA_ARG_TENSOR_SPLIT)
-mg, --main-gpu INDEX the GPU to use for the model (with split-mode = none), or for
intermediate results and KV (with split-mode = row) (default: 0)
(env: LLAMA_ARG_MAIN_GPU)
--check-tensors check model tensor data for invalid values (default: false)
--override-kv KEY=TYPE:VALUE advanced option to override model metadata by key. may be specified
multiple times.
types: int, float, bool, str. example: --override-kv
tokenizer.ggml.add_bos_token=bool:false
--lora FNAME path to LoRA adapter (can be repeated to use multiple adapters)
--lora-scaled FNAME SCALE path to LoRA adapter with user defined scaling (can be repeated to use
multiple adapters)
--control-vector FNAME add a control vector
note: this argument can be repeated to add multiple control vectors
--control-vector-scaled FNAME SCALE add a control vector with user defined scaling SCALE
note: this argument can be repeated to add multiple scaled control
vectors
--control-vector-layer-range START END
layer range to apply the control vector(s) to, start and end inclusive
-m, --model FNAME model path (default: `models/$filename` with filename from `--hf-file`
or `--model-url` if set, otherwise models/7B/ggml-model-f16.gguf)
(env: LLAMA_ARG_MODEL)
-mu, --model-url MODEL_URL model download url (default: unused)
(env: LLAMA_ARG_MODEL_URL)
-hf, -hfr, --hf-repo <user>/<model>[:quant]
Hugging Face model repository; quant is optional, case-insensitive,
default to Q4_K_M, or falls back to the first file in the repo if
Q4_K_M doesn't exist.
example: unsloth/phi-4-GGUF:q4_k_m
(default: unused)
(env: LLAMA_ARG_HF_REPO)
-hfd, -hfrd, --hf-repo-draft <user>/<model>[:quant]
Same as --hf-repo, but for the draft model (default: unused)
(env: LLAMA_ARG_HFD_REPO)
-hff, --hf-file FILE Hugging Face model file. If specified, it will override the quant in
--hf-repo (default: unused)
(env: LLAMA_ARG_HF_FILE)
-hfv, -hfrv, --hf-repo-v <user>/<model>[:quant]
Hugging Face model repository for the vocoder model (default: unused)
(env: LLAMA_ARG_HF_REPO_V)
-hffv, --hf-file-v FILE Hugging Face model file for the vocoder model (default: unused)
(env: LLAMA_ARG_HF_FILE_V)
-hft, --hf-token TOKEN Hugging Face access token (default: value from HF_TOKEN environment
variable)
(env: HF_TOKEN)
--log-disable Log disable
--log-file FNAME Log to file
--log-colors Enable colored logging
(env: LLAMA_LOG_COLORS)
-v, --verbose, --log-verbose Set verbosity level to infinity (i.e. log all messages, useful for
debugging)
-lv, --verbosity, --log-verbosity N Set the verbosity threshold. Messages with a higher verbosity will be
ignored.
(env: LLAMA_LOG_VERBOSITY)
--log-prefix Enable prefx in log messages
(env: LLAMA_LOG_PREFIX)
--log-timestamps Enable timestamps in log messages
(env: LLAMA_LOG_TIMESTAMPS)
----- sampling params -----
--samplers SAMPLERS samplers that will be used for generation in the order, separated by
';'
(default: penalties;dry;top_k;typ_p;top_p;min_p;xtc;temperature)
-s, --seed SEED RNG seed (default: -1, use random seed for -1)
--sampling-seq, --sampler-seq SEQUENCE
simplified sequence for samplers that will be used (default: edkypmxt)
--ignore-eos ignore end of stream token and continue generating (implies
--logit-bias EOS-inf)
--temp N temperature (default: 0.8)
--top-k N top-k sampling (default: 40, 0 = disabled)
--top-p N top-p sampling (default: 0.9, 1.0 = disabled)
--min-p N min-p sampling (default: 0.1, 0.0 = disabled)
--xtc-probability N xtc probability (default: 0.0, 0.0 = disabled)
--xtc-threshold N xtc threshold (default: 0.1, 1.0 = disabled)
--typical N locally typical sampling, parameter p (default: 1.0, 1.0 = disabled)
--repeat-last-n N last n tokens to consider for penalize (default: 64, 0 = disabled, -1
= ctx_size)
--repeat-penalty N penalize repeat sequence of tokens (default: 1.0, 1.0 = disabled)
--presence-penalty N repeat alpha presence penalty (default: 0.0, 0.0 = disabled)
--frequency-penalty N repeat alpha frequency penalty (default: 0.0, 0.0 = disabled)
--dry-multiplier N set DRY sampling multiplier (default: 0.0, 0.0 = disabled)
--dry-base N set DRY sampling base value (default: 1.75)
--dry-allowed-length N set allowed length for DRY sampling (default: 2)
--dry-penalty-last-n N set DRY penalty for the last n tokens (default: -1, 0 = disable, -1 =
context size)
--dry-sequence-breaker STRING add sequence breaker for DRY sampling, clearing out default breakers
('\n', ':', '"', '*') in the process; use "none" to not use any
sequence breakers
--dynatemp-range N dynamic temperature range (default: 0.0, 0.0 = disabled)
--dynatemp-exp N dynamic temperature exponent (default: 1.0)
--mirostat N use Mirostat sampling.
Top K, Nucleus and Locally Typical samplers are ignored if used.
(default: 0, 0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0)
--mirostat-lr N Mirostat learning rate, parameter eta (default: 0.1)
--mirostat-ent N Mirostat target entropy, parameter tau (default: 5.0)
-l, --logit-bias TOKEN_ID(+/-)BIAS modifies the likelihood of token appearing in the completion,
i.e. `--logit-bias 15043+1` to increase likelihood of token ' Hello',
or `--logit-bias 15043-1` to decrease likelihood of token ' Hello'
--grammar GRAMMAR BNF-like grammar to constrain generations (see samples in grammars/
dir) (default: '')
--grammar-file FNAME file to read grammar from
-j, --json-schema SCHEMA JSON schema to constrain generations (https://json-schema.org/), e.g.
`{}` for any JSON object
For schemas w/ external $refs, use --grammar +
example/json_schema_to_grammar.py instead
----- example-specific params -----
--no-display-prompt don't print prompt at generation (default: false)
-co, --color colorise output to distinguish prompt and user input from generations
(default: false)
--no-context-shift disables context shift on inifinite text generation (default:
disabled)
(env: LLAMA_ARG_NO_CONTEXT_SHIFT)
-ptc, --print-token-count N print token count every N tokens (default: -1)
--prompt-cache FNAME file to cache prompt state for faster startup (default: none)
--prompt-cache-all if specified, saves user input and generations to cache as well
--prompt-cache-ro if specified, uses the prompt cache but does not update it
-r, --reverse-prompt PROMPT halt generation at PROMPT, return control in interactive mode
-sp, --special special tokens output enabled (default: false)
-cnv, --conversation run in conversation mode:
- does not print special tokens and suffix/prefix
- interactive mode is also enabled
(default: auto enabled if chat template is available)
-no-cnv, --no-conversation force disable conversation mode (default: false)
-i, --interactive run in interactive mode (default: false)
-if, --interactive-first run in interactive mode and wait for input right away (default: false)
-mli, --multiline-input allows you to write or paste multiple lines without ending each in '\'
--in-prefix-bos prefix BOS to user inputs, preceding the `--in-prefix` string
--in-prefix STRING string to prefix user inputs with (default: empty)
--in-suffix STRING string to suffix after user inputs with (default: empty)
--no-warmup skip warming up the model with an empty run
-gan, --grp-attn-n N group-attention factor (default: 1)
(env: LLAMA_ARG_GRP_ATTN_N)
-gaw, --grp-attn-w N group-attention width (default: 512)
(env: LLAMA_ARG_GRP_ATTN_W)
--jinja use jinja template for chat (default: disabled)
(env: LLAMA_ARG_JINJA)
--chat-template JINJA_TEMPLATE set custom jinja chat template (default: template taken from model's
metadata)
if suffix/prefix are specified, template will be disabled
only commonly used templates are accepted (unless --jinja is set
before this flag):
list of built-in templates:
chatglm3, chatglm4, chatml, command-r, deepseek, deepseek2, deepseek3,
exaone3, falcon3, gemma, gigachat, glmedge, granite, llama2,
llama2-sys, llama2-sys-bos, llama2-sys-strip, llama3, megrez, minicpm,
mistral-v1, mistral-v3, mistral-v3-tekken, mistral-v7, monarch,
openchat, orion, phi3, phi4, rwkv-world, vicuna, vicuna-orca, zephyr
(env: LLAMA_ARG_CHAT_TEMPLATE)
--chat-template-file JINJA_TEMPLATE_FILE
set custom jinja chat template file (default: template taken from
model's metadata)
if suffix/prefix are specified, template will be disabled
only commonly used templates are accepted (unless --jinja is set
before this flag):
list of built-in templates:
chatglm3, chatglm4, chatml, command-r, deepseek, deepseek2, deepseek3,
exaone3, falcon3, gemma, gigachat, glmedge, granite, llama2,
llama2-sys, llama2-sys-bos, llama2-sys-strip, llama3, megrez, minicpm,
mistral-v1, mistral-v3, mistral-v3-tekken, mistral-v7, monarch,
openchat, orion, phi3, phi4, rwkv-world, vicuna, vicuna-orca, zephyr
(env: LLAMA_ARG_CHAT_TEMPLATE_FILE)
--simple-io use basic IO for better compatibility in subprocesses and limited
consoles
example usage:
text generation: llama-cli.exe -m your_model.gguf -p "I believe the meaning of life is" -n 128
chat (conversation): llama-cli.exe -m your_model.gguf -p "You are a helpful assistant" -cnv
Первый момент, который я обнаружил — при предложенном параметре -n 256 вывод останавливался «на полуслове», не доходя до конца (это количество токенов — number of tokens to predict), я увеличил его до 4096 и процесс пошёл. Можно вообще не указывать, но есть риск того, что её поток сознания не остановится.
Если кому интересен полный лог старта, то вот:
llama-cli.exe -m DeepSeek-R1.Q8_0-00001-of-00015.gguf ...
Far Manager, version 3.0.6000.0 x64
Copyright © 1996-2000 Eugene Roshal, Copyright © 2000-2022 Far Group
F:>llama-cli.exe -m DeepSeek-R1.Q8_0-00001-of-00015.gguf -p "Hi!" -n 4096
build: 4628 (cde38332) with MSVC 19.42.34436.0 for x64
main: llama backend init
main: load the model and apply lora adapter, if any
llama_model_loader: additional 14 GGUFs metadata loaded.
llama_model_loader: loaded meta data with 48 key-value pairs and 1025 tensors from DeepSeek-R1.Q8_0-00001-of-00015.gguf (version GGUF V3 (latest))
llama_model_loader: Dumping metadata keys/values. Note: KV overrides do not apply in this output.
llama_model_loader: - kv 0: general.architecture str
= deepseek2
llama_model_loader: - kv 1: general.type str
= model
llama_model_loader: - kv 2: general.name str
= DeepSeek R1 BF16
llama_model_loader: - kv 3: general.quantized_by str
= Unsloth
llama_model_loader: - kv 4: general.size_label str
= 256x20B
llama_model_loader: - kv 5: general.repo_url str
= https://huggingface.co/unsloth
llama_model_loader: - kv 6: deepseek2.block_count u32
= 61
llama_model_loader: - kv 7: deepseek2.context_length u32
= 163840
llama_model_loader: - kv 8: deepseek2.embedding_length u32
= 7168
llama_model_loader: - kv 9: deepseek2.feed_forward_length u32
= 18432
llama_model_loader: - kv 10: deepseek2.attention.head_count u32
= 128
llama_model_loader: - kv 11: deepseek2.attention.head_count_kv u32
= 128
llama_model_loader: - kv 12: deepseek2.rope.freq_base f32
= 10000.000000
llama_model_loader: - kv 13: deepseek2.attention.layer_norm_rms_epsilon f32
= 0.000001
llama_model_loader: - kv 14: deepseek2.expert_used_count u32
= 8
llama_model_loader: - kv 15: general.file_type u32
= 7
llama_model_loader: - kv 16: deepseek2.leading_dense_block_count u32
= 3
llama_model_loader: - kv 17: deepseek2.vocab_size u32
= 129280
llama_model_loader: - kv 18: deepseek2.attention.q_lora_rank u32
= 1536
llama_model_loader: - kv 19: deepseek2.attention.kv_lora_rank u32
= 512
llama_model_loader: - kv 20: deepseek2.attention.key_length u32
= 192
llama_model_loader: - kv 21: deepseek2.attention.value_length u32
= 128
llama_model_loader: - kv 22: deepseek2.expert_feed_forward_length u32
= 2048
llama_model_loader: - kv 23: deepseek2.expert_count u32
= 256
llama_model_loader: - kv 24: deepseek2.expert_shared_count u32
= 1
llama_model_loader: - kv 25: deepseek2.expert_weights_scale f32
= 2.500000
llama_model_loader: - kv 26: deepseek2.expert_weights_norm bool
= true
llama_model_loader: - kv 27: deepseek2.expert_gating_func u32
= 2
llama_model_loader: - kv 28: deepseek2.rope.dimension_count u32
= 64
llama_model_loader: - kv 29: deepseek2.rope.scaling.type str
= yarn
llama_model_loader: - kv 30: deepseek2.rope.scaling.factor f32
= 40.000000
llama_model_loader: - kv 31: deepseek2.rope.scaling.original_context_length u32
= 4096
llama_model_loader: - kv 32: deepseek2.rope.scaling.yarn_log_multiplier f32
= 0.100000
llama_model_loader: - kv 33: tokenizer.ggml.model str
= gpt2
llama_model_loader: - kv 34: tokenizer.ggml.pre str
= deepseek-v3
llama_model_loader: - kv 35: tokenizer.ggml.tokens arr[str,129280] = ["<|begin▁of▁sentence|>", "<�...
llama_model_loader: - kv 36: tokenizer.ggml.token_type arr[i32,129280] = [3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
llama_model_loader: - kv 37: tokenizer.ggml.merges arr[str,127741] = ["Ġ t", "Ġ a", "i n", "Ġ Ġ", "h e...
llama_model_loader: - kv 38: tokenizer.ggml.bos_token_id u32
= 0
llama_model_loader: - kv 39: tokenizer.ggml.eos_token_id u32
= 1
llama_model_loader: - kv 40: tokenizer.ggml.padding_token_id u32
= 128815
llama_model_loader: - kv 41: tokenizer.ggml.add_bos_token bool
= true
llama_model_loader: - kv 42: tokenizer.ggml.add_eos_token bool
= false
llama_model_loader: - kv 43: tokenizer.chat_template str
= {% if not add_generation_prompt is de...
llama_model_loader: - kv 44: general.quantization_version u32
= 2
llama_model_loader: - kv 45: split.no u16
= 0
llama_model_loader: - kv 46: split.count u16
= 15
llama_model_loader: - kv 47: split.tensors.count i32
= 1025
llama_model_loader: - type f32: 361 tensors
llama_model_loader: - type q8_0: 664 tensors
print_info: file format = GGUF V3 (latest)
print_info: file type = Q8_0
print_info: file size = 664.29 GiB (8.50 BPW)
load: special_eos_id is not in special_eog_ids - the tokenizer config may be incorrect load: special tokens cache size = 819
load: token to piece cache size = 0.8223 MB
print_info: arch = deepseek2
print_info: vocab_only = 0
print_info: n_ctx_train = 163840
print_info: n_embd = 7168
print_info: n_layer = 61
print_info: n_head = 128
print_info: n_head_kv = 128
print_info: n_rot = 64
print_info: n_swa = 0
print_info: n_embd_head_k = 192
print_info: n_embd_head_v = 128
print_info: n_gqa = 1
print_info: n_embd_k_gqa = 24576
print_info: n_embd_v_gqa = 16384
print_info: f_norm_eps = 0.0e+00
print_info: f_norm_rms_eps = 1.0e-06
print_info: f_clamp_kqv = 0.0e+00
print_info: f_max_alibi_bias = 0.0e+00
print_info: f_logit_scale = 0.0e+00
print_info: n_ff = 18432
print_info: n_expert = 256
print_info: n_expert_used = 8
print_info: causal attn = 1
print_info: pooling type = 0
print_info: rope type = 0
print_info: rope scaling = yarn
print_info: freq_base_train = 10000.0
print_info: freq_scale_train = 0.025
print_info: n_ctx_orig_yarn = 4096
print_info: rope_finetuned = unknown
print_info: ssm_d_conv = 0
print_info: ssm_d_inner = 0
print_info: ssm_d_state = 0
print_info: ssm_dt_rank = 0
print_info: ssm_dt_b_c_rms = 0
print_info: model type = 671B
print_info: model params = 671.03 B
print_info: general.name = DeepSeek R1 BF16
print_info: n_layer_dense_lead = 3
print_info: n_lora_q = 1536
print_info: n_lora_kv = 512
print_info: n_ff_exp = 2048
print_info: n_expert_shared = 1
print_info: expert_weights_scale = 2.5
print_info: expert_weights_norm = 1
print_info: expert_gating_func = sigmoid
print_info: rope_yarn_log_mul = 0.1000
print_info: vocab type = BPE
print_info: n_vocab = 129280
print_info: n_merges = 127741
print_info: BOS token = 0 '<|begin▁of▁sentence|>'
print_info: EOS token = 1 '<|end▁of▁sentence|>'
print_info: EOT token = 1 '<|end▁of▁sentence|>'
print_info: PAD token = 128815 '<|PAD▁TOKEN|>'
print_info: LF token = 201 'Ċ'
print_info: FIM PRE token = 128801 '<|fim▁begin|>'
print_info: FIM SUF token = 128800 '<|fim▁hole|>'
print_info: FIM MID token = 128802 '<|fim▁end|>'
print_info: EOG token = 1 '<|end▁of▁sentence|>'
print_info: max token length = 256
load_tensors: offloading 0 repeating layers to GPU
load_tensors: offloaded 0/62 layers to GPU
load_tensors: CPU_Mapped model buffer size = 45565.90 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 46661.11 MiB
load_tensors: CPU_Mapped model buffer size = 28077.60 MiB
llama_init_from_model: n_seq_max = 1
llama_init_from_model: n_ctx = 4096
llama_init_from_model: n_ctx_per_seq = 4096
llama_init_from_model: n_batch = 2048
llama_init_from_model: n_ubatch = 512
llama_init_from_model: flash_attn = 0
llama_init_from_model: freq_base = 10000.0
llama_init_from_model: freq_scale = 0.025
llama_init_from_model: n_ctx_per_seq (4096) < n_ctx_train (163840) -- the full capacity of the model will not be utilized
llama_kv_cache_init: kv_size = 4096, offload = 1, type_k = 'f16', type_v = 'f16', n_layer = 61, can_shift = 0
llama_kv_cache_init: CPU KV buffer size = 19520.00 MiB
llama_init_from_model: KV self size = 19520.00 MiB, K (f16): 11712.00 MiB, V (f16): 7808.00 MiB
llama_init_from_model: CPU output buffer size = 0.49 MiB
llama_init_from_model: CPU compute buffer size = 1186.01 MiB
llama_init_from_model: graph nodes = 5025
llama_init_from_model: graph splits = 1
common_init_from_params: KV cache shifting is not supported for this model, disabling KV cache shifting
common_init_from_params: setting dry_penalty_last_n to ctx_size = 4096
common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
main: llama threadpool init, n_threads = 28
main: chat template is available, enabling conversation mode (disable it with -no-cnv) main: chat template example:
You are a helpful assistant
<|User|>Hello<|Assistant|>Hi there<|end▁of▁sentence|><|User|>How are you?<|Ass
istant|>
system_info: n_threads = 28 (n_threads_batch = 28) / 28 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | AVX512 = 1 | LLAMAFILE = 1 | OPENMP = 1 | AARCH64_REPACK = 1 |
main: interactive mode on.
sampler seed: 526007933
sampler params:
repeat_last_n = 64, repeat_penalty = 1.000, frequency_penalty = 0.000, presence_penalty = 0.000
dry_multiplier = 0.000, dry_base = 1.750, dry_allowed_length = 2, dry_penalty_last_n = 4096
top_k = 40, top_p = 0.950, min_p = 0.050, xtc_probability = 0.000, xtc_threshold = 0.100, typical_p = 1.000, temp = 0.800
mirostat = 0, mirostat_lr = 0.100, mirostat_ent = 5.000
sampler chain: logits -> logit-bias -> penalties -> dry -> top-k -> typical -> top-p -> min-p -> xtc -> temp-ext -> dist
generate: n_ctx = 4096, n_batch = 2048, n_predict = 4096, n_keep = 1
== Running in interactive mode. ==
Press Ctrl+C to interject at any time.
Press Return to return control to the AI.
To return control without starting a new line, end your input with '/'.
If you want to submit another line, end your input with ''.
Hi!
«Работаем»
Ну вот прям «работой» это назвать сложно, потому что это всё отчаянно медленно.
Сразу после запуска модель целиком в память не грузится (точнее не «коммитится»), она как бы «догружается» при общении и количество занятой памяти растёт по мере работы, выходя на «плато» после двух-трёх промптов.
При первом «холодном» старте до появления приглашения проходит почти две минуты, дальше она радует нас примерно токеном в секунду.
Я смастерил такую вот несложную оснастку, показывающую загрузку памяти и процессора, ну и таймер до кучи, что б вы прочувствовали эту боль (я ещё вырезал примерно минуту, пока часть модели грузилась с диска в память, остальное оставлю в реальном времени как есть):
Как видите, память заполнилась примерно на треть после старта и чуть более чем наполовину после первого промпта.
Если вводить следующие вопросы, то модель будет догружаться. Нет смысла мучить вас медленным выводом, я буду снимать кадр в секунду, проигрывая гифку с примерно двадцатикратным ускорением. Попросим у неё Рунге-Кутта, хорошо видно, как она на ходу задействует семьсот гигабайт памяти почти под завязку:
Вот вывод «как есть»:
Can you please provide C code of Runge Kutta Method for (x-y)/(x+y)?
Hi, DeepSeek!
Hi! How can I assist you today?
Can you please provide C code of Runge Kutta Method for (x-y)/(x+y)?
Certainly! The Runge-Kutta method is a numerical technique used to solve ordinary differential equations (ODEs). For the differential equation dy/dx = (x - y)/(x + y), we can apply the 4th-order Runge-Kutta method (RK4). Here's a C code implementation:
#include <stdio.h>
#include <math.h>
// Define the differential equation dy/dx = (x - y)/(x + y)
double f(double x, double y) {
return (x - y) / (x + y);
}
// 4th-order Runge-Kutta method
void rungeKutta4(double x0, double y0, double h, double x_target) {
double x = x0;
double y = y0;
double k1, k2, k3, k4;
printf("Initial conditions: x = %lf, y = %lf\n", x, y);
while (x < x_target) {
if (x + h > x_target) {
h = x_target - x; // Adjust step to reach x_target exactly
}
k1 = h * f(x, y);
k2 = h * f(x + h/2, y + k1/2);
k3 = h * f(x + h/2, y + k2/2);
k4 = h * f(x + h, y + k3);
y = y + (k1 + 2*k2 + 2*k3 + k4)/6;
x = x + h;
printf("x = %lf, y = %lf\n", x, y);
}
}
int main() {
double x0 = 1.0; // Initial x
double y0 = 0.0; // Initial y
double h = 0.1; // Step size
double x_target = 2.0; // Target x value
rungeKutta4(x0, y0, h, x_target);
return 0;
}
Important Notes:
Initial Conditions: The current example uses
x0=1.0
,y0=0.0
, step sizeh=0.1
, and integrates up tox_target=2.0
. Adjust these values as needed.Division by Zero: The function
f(x,y)
will have a division by zero ifx + y = 0
. Ensure your initial conditions and step size avoid this scenario.Adaptive Step Size: For better accuracy, you might want to implement adaptive step size control, but this example uses a fixed step size for simplicity.
Output: The code prints the solution at each step. Modify the
printf
statements as needed for your use case.
Let me know if you need further clarification!
На всё про всё у неё ушло десять минут реального времени (проверку корректности решения оставим за кадром). Процессор, как видите, был занят чуть больше чем на половину. Тут надо заметить, что у меня был включён гипертрединг (ну или гиперпоточность), так что сегодня утром первым делом я его отключил и повторил эксперимент, и да, отключение НТ уверенно кладёт стрелку нашего спидометра на ограничитель, теперь все ядра активно заняты (кстати, конкретно этот hp вовсе не ревёт при этом как самолёт, идущий на взлёт, что приятно):
По скорости сильных изменений в производительности я не заметил, примерно тоже самое, токен в секунду или около того. Но гораздо интереснее тут другое. Шёл второй день экспериментов, я и пожелал модели доброго утра (я обычно вежливый, да, в том числе с ИИ). Она очень обрадовалась, просветлела (даже несмотря на то, что я ошибся в имени), и на мой стандартный вопрос про Рунге-Кутта пустилась в пространные размышления о смысле жизни на сорок минут (время в гифке выше).
И вот тут как раз возник тот «ага!» момент, о котором много где упоминали, когда модель выдаёт что-то типа "Wait, but the step function can be part of the loop. Alternatively, write a function that takes x, y, h, and returns the new y..."
Вообще я считаю, что выданная простыня вполне заслуживает того, чтобы быть приведённой полностью.
Очень много букв
Good morning, DeppSeek!
Okay, the user greeted me with "Good morning, DeppSeek!" Let me start by acknowledging their greeting and setting a friendly tone. Maybe I should respond with a cheerful good morning and ask how I can assist them today. Since they might need help with something specific, I should keep the response open-ended to encourage them to share their request. I'll make sure to keep it concise and welcoming.
Good morning! � How can I assist you today? Whether it's brainstorming ideas, solving
a problem, or just chatting, I'm here to help! Let me know what's on your mind. �
Please provide C code for Runge Kutta method for (x-y)/(x+y)
Okay, the user is asking for C code that implements the Runge-Kutta method for the differential equation given by (x - y)/(x + y). Let me start by recalling what the Runge-Kutta method is. The fourth-order Runge-Kutta (RK4) method is a numerical technique used to solve ordinary differential equations (ODEs) with a given initial condition. It's more accurate than Euler's method because it uses multiple intermediate steps to approximate the solution over each interval.
First, I need to confirm the ODE the user wants to solve. The function provided is (x - y)/(x + y). Typically, ODEs are expressed as dy/dx = f(x, y), so I'll assume that the differential equation here is dy/dx = (x - y)/(x + y). That makes sense.
Next, I should outline the RK4 method. The RK4 method computes the next value y_{n+1} using the current value y_n and the weighted average of four increments:
k1 = h * f(x_n, y_n)
k2 = h * f(x_n + h/2, y_n + k1/2)
k3 = h * f(x_n + h/2, y_n + k2/2)
k4 = h * f(x_n + h, y_n + k3)
Then, y_{n+1} = y_n + (k1 + 2k2 + 2k3 + k4)/6
So, in the C code, I'll need to implement this formula.
The user wants a C program. Let me structure the code step by step. The code should include the necessary headers, define the function f(x, y) corresponding to the ODE, and implement the RK4 step as a function. Then, in the main function, set the initial conditions, step size h, number of steps, and loop through each step to compute the solution.
Wait, initial conditions are needed. Since the user didn't specify them, I should choose a default initial value, say x0, y0, and a range for x. Let's assume the user wants to start at some x0 (like 0) with y0, and compute up to a certain point. But since the user didn't specify, perhaps the code should take initial values, step size, and number of steps as inputs or define them as constants. To make it simple, maybe hardcode initial x and y, step size h, and the number of steps. Then, in the code comments, mention that these can be adjusted.
Also, need to be cautious about division by zero in the function (x + y) could be zero. The code should handle cases where x + y is zero, but since the user hasn't specified error handling, perhaps just note that in the comments.
Let me outline the code:
Include standard headers (stdio.h, math.h if needed, but here maybe not necessary). 2. Define the function f(x, y) which returns (x - y)/(x + y).
Implement the RK4 step function that takes current x, y, step h, computes k1-k4, updates y.
In main, set initial x0, y0, h, number of steps.
Loop over the steps, compute each step, print x and y.
But let's test this with an example. Suppose initial x0 is 1, y0 is 1, h=0.1, and compute a few steps. Wait, but if x0=1 and y0=1, then x + y = 2, so the function is (1-1)/2 = 0. So the first step would compute k1 to k4 based on that. However, if x and y start at 0, the denominator is zero. So need to ensure the initial values don't cause division by zero. So perhaps in the code example, choose x0=1, y0=2, just to have a safe starting point.
Alternatively, ask the user for input. But since the user didn't specify, it's better to hardcode values and mention in comments to adjust them.
Another point: in the code, when computing x, since the ODE is dy/dx = f(x,y), each step advances x by h. So in the main loop, after each step, x increases by h.
Putting it all together:
The code will have:
Function definition for f(x, y)
A function to perform one RK4 step
Main function with loop
Wait, but the step function can be part of the loop. Alternatively, write a function that takes x, y, h, and returns the new y.
Yes, that's better. So:
double rungeKuttaStep(double x, double y, double h) {
compute k1, k2, k3, k4
return y + (k1 + 2*k2 + 2*k3 + k4)/6;
}
But since each k depends on evaluations at different points, need to compute them step by step.
So here's the step-by-step code:
#include <stdio.h>
double f(double x, double y) {
return (x - y) / (x + y);
}
void rungeKutta4(double *x, double *y, double h) {
double k1 = h * f(*x, *y);
double k2 = h * f(*x + h/2, *y + k1/2);
double k3 = h * f(*x + h/2, *y + k2/2);
double k4 = h * f(*x + h, *y + k3);
*y += (k1 + 2*k2 + 2*k3 + k4) / 6;
*x += h;
}
int main() {
double x0 = 1.0; // Initial x
double y0 = 2.0; // Initial y
double h = 0.1; // Step size
int steps = 10; // Number of steps
printf("Initial conditions: x = %f, y = %f\n", x0, y0);
printf("Step size: %f\n", h);
printf("Number of steps: %d\n\n", steps);
for (int i = 0; i < steps; i++) {
rungeKutta4(&x0, &y0, h);
printf("Step %d: x = %f, y = %f\n", i+1, x0, y0);
}
return 0;
}
Wait, no: in each call to rungeKutta4, x is incremented by h. But the loop in main is called steps times, so after each step, x increases by h. That's correct.
Wait, in the initial code, x0 starts at 1.0. Then, after the first call to rungeKutta4, x0 becomes 1.0 + h (since *x +=h). So the first step's x is 1.1, and the y is updated. That's correct.
But in RK4, when you compute k1, you use x_n, then k2 and k3 use x_n + h/2, and k4 uses x_n + h. Then, after all, x increments by h. So that's accurate.
Now, let's check if the function f is correctly implemented. Yes, (x - y)/(x + y).
But wait, the user wrote the differential equation as (x - y)/(x + y). So dy/dx = (x - y)/(x + y). The code correctly returns that.
Potential issues: division by zero when x + y is zero. But the example initial conditions x0=1.0 and y0=2.0 avoid that. The user may need to adjust initial conditions accordingly.
Also, the code prints after each step, showing x and y.
But the user might want to integrate over a specific interval. Let's see: if h=0.1 and steps=10, x goes from 1.0 to 1.0 + 10*0.1=2.0.
Yes. So the code as written is correct.
I should test this code to ensure there are no syntax errors. Let me see:
The function rungeKutta4 takes pointers to x and y, modifies them in place.
The main function loops steps times, each time calling the function and printing.
The f function is correctly defined.
Yes, this should compile and run.
However, in the main loop, the initial print is before the loop, so the initial x and y are printed, then the loop starts. But the first call to rungeKutta4 modifies x0 and y0 to the next step. Then, the first printed step is after the first update. So the first printed step is Step 1: x=1.1, y= updated value.
If the user wants to see the values at each step including the initial, maybe the code should print before updating. But in the code as written, the initial conditions are printed once, then the loop starts, updates, and prints the new x and y each time. So the output shows the progression from the initial step onwards. That's okay.
Alternatively, adjust the code to print after each step, which is what is done here.
I think this code should work. Therefore, the answer should include this code with explanations of the parameters and a note about potential division by zero.
Here's a C implementation of the 4th-order Runge-Kutta method for the differential equation dy/dx = (x - y)/(x + y):
#include <stdio.h>
// Define the differential equation dy/dx = (x - y)/(x + y)
double f(double x, double y) {
return (x - y)/(x + y);
}
// Performs one iteration of RK4 method
void rk4_step(double *x, double *y, double h) {
double k1 = h * f(*x, *y);
double k2 = h * f(*x + h/2, *y + k1/2);
double k3 = h * f(*x + h/2, *y + k2/2);
double k4 = h * f(*x + h, *y + k3);
*y += (k1 + 2*k2 + 2*k3 + k4)/6;
*x += h;
}
int main() {
// Initial conditions
double x0 = 1.0; // Initial x-value
double y0 = 0.5; // Initial y-value
double h = 0.1; // Step size
int steps = 10; // Number of steps
printf("Starting at: x = %.2f, y = %.2f\n", x0, y0);
printf("Step size: %.2f\n", h);
printf("Number of steps: %d\n\n", steps);
for(int i = 1; i <= steps; i++) {
rk4_step(&x0, &y0, h);
printf("Step %2d: x = %.3f, y = %.6f\n", i, x0, y0);
}
return 0;
}
Key components:
f(x, y)
- Implements the differential equationrk4_step()
- Performs one RK4 iteration-
main()
- Controls the simulation with parameters:Initial conditions (x0, y0)
Step size (h)
Number of steps
Notes:
Adjust
x0
,y0
,h
, andsteps
as neededBe cautious when x + y = 0 (potential division by zero)
Accuracy depends on step size h (smaller h = more precision)
Output shows x/y values at each step
To use this program:
Compile with any C compiler (e.g.,
gcc rk4.c -o rk4
)Run the executable
Modify initial values for different starting conditions
Would you like me to explain any part in more detail or modify specific aspects of the implementation?
Насколько этот опус лучше того, что был приведён выше, это уже другой вопрос, но разительным образом отличающийся ответ от предыдущего при почти идентичном промпте — это любопытный момент (параметры запуска я, ясное дело, никак не менял).
Кстати, о параметрах. Есть два режима запуска.
Первый вот такой, он называется "Text generation":
llama-cli.exe -m your_model.gguf -p "Hi!" -n 4096
А второй с ключом -cnv — "Сhat (conversation)"
llama-cli.exe -m your_model.gguf -p "Hello!" -cnv
Первый используется в том случае, если искуственный интеллект пишет за вас диссертацию, а второй — если он используется в качестве собеседника (чат-бота). При этом инструкция говорит, что модель должна быть «заточена» под этот режим. В принципе вы можете попросить её саму рассказать об отличиях, она напишет, что в Чат режиме можно использовать структурированные реплики с метками (например, [INST], <<SYS>>), останавливать её токенами конца диалога (например, </s>) и что то там ещё.
Я попробовал и так и сяк и основное отличие, которое заметил, это то, что объяснения в режиме «чат общения» сопровождаются готовыми формулами в TeX формате, выглядит это вот так, если я вставлю вывод прямо в редактор хабра:
Explanation:
Function
f
: Implements the differential equation
-
RK4 Method:
Takes initial conditions
(x0, y0)
, step sizeh
, and targetx_target
.-
Iteratively computes the next y using the RK4 formulas:
...
Вообще я верю, что если я попрошу переписать формулы в таком формате, она это по любому сделает, независимо от режима запуска, но просто вот такое наблюдение. Надо будет поэкспериментировать с другими моделями.
Ну а так — русский вроде знает:
Грамматику правит, альтернативы предлагает, историю общения помнит:
В стихах тоже может, по-немецки в том числе. Похоже, моя исходящая деловая корреспонденция станет несколько разнообразнее.
Короче у меня под столом завёлся личный секретарь, хоть и чутка тормознутый. Гугль, википедия, вольфрам математика, словарь, корректор в одном флаконе, да ещё и на разных языках. Если вы хотите его (или её) о чём-нибудь спросить — не стесняйтесь, задавайте вопросы в комментах, я с удовольствием передам ваши вопросы и опубликую ответы.
При завершении работы выдаёт статистику, около одного токена в секунду:
llama_perf_sampler_print: sampling time = 52.33 ms / 209 runs (0.25 ms per token, 3993.66 tokens per second)
llama_perf_context_print: load time = 89790.30 ms
llama_perf_context_print: prompt eval time = 87115.12 ms / 112 tokens (777.81 ms per token, 1.29 tokens per second)
llama_perf_context_print: eval time = 1883493.69 ms / 1777 runs (1059.93 ms per token, 0.94 tokens per second)
llama_perf_context_print: total time = 3136520.40 ms / 1889 tokens
Кому не нравится консоль, можно запустить и вот так:
llama-server.exe -m DeepSeek-R1.Q8_0-00001-of-00015.gguf --port 8082
Эта штука поднимет веб сервер (по умолчанию на порту 8080, но он у меня занят, так что 8082), будет красивее:
Плюс там в настройках можно кое-что подкрутить, например она может писать количество токенов в секунду в каждом ответе, но меня консоль в общем не смущает.
Производительность
Она, конечно удручает. Безусловно, более быстрая память типа DDR5 слегка улучшит ситуацию. В идеале надо иметь быструю GPU память, но пяток адаптеров типа NVIDIA H200, у которых по 141 ГБ памяти с пропускной способностью под пять терабайт в секунду сразу отправят нас в мир шестизначных ценников.
Что по этой конфигурации, то там можно ещё немного попытаться подкрутить в BIOS.
Некоторый потенцал, возможно, кроется в NUMA:
Пока что там не всё хорошо, но общественность этим уже озаботилась, на гитхабе висит открытый тикет — Feature Request: NUMA-aware MoE Expert Allocation for Improved Performanc #11333. Вообще когда мы упираемся в пропускную способность памяти — как отметили в комментах к изначальному посту с точки зрения эффективности не очень хорошо иметь два процессора, конкурирующих за общую память (хотя эффективная работа с двенадцатиканальной памятью на двухпроцессорной системе вкупе с NUMA — это отдельная тема, требующая дотошной проверки и бенчмарков).
По параметрам запуска я сильно не лазал, возможно там тоже что-то можно подкрутить.
Можно пересобрать всё из исходников и посмотреть, где проседает производительность и пройтись по «горячим точкам», да хоть тем же Intel VTune.
Но уже понятно, что сильно быстрее от этого не станет, и даже если раскочегарить всё вдвое-втрое, этого будет мало, надо раз этак в двадцать быстрее.
Некоторая надежда на OpenVINO, по идее там примерно вот так можно запуститься, если из Питона:
import openvino_genai
# will run the model on CPU, GPU, or NPU are possible options
pipe = openvino_genai.LLMPipeline("F:\<Тут Модель>", "CPU")
print(pipe.generate("The answer to life, the universe, and everything?", max_new_tokes =4096)
Но напрямую gguf не поддерживается, там конвертировать надо, пока не брался. Если кто-нибудь уже делал подход к этому снаряду — напишите, пожалуйста в комментах.
AVX-512 — тоже отдельная тема, бывает и так, что код, черезчур активно использующий эти инструкции, начинает притормаживать из-за того, что процессор снижает частоту (ему слишком много транзисторов одномоментно переключать бывает сложновато и он греется), кроме того разные компиляторы отличаются эффективностью кодогенерации, можно попробовать пересобрать, скажем Intel OneAPI.
Если брать не такие увесистые модели, то, конечно, всё работает резвее, но и «качество» вывода падает — для того же Рунге-Кутта описание алгоритма ещё выдаётся, а вот исходный код — уже нет (хотя есть «coder» модели, заточенные как раз под написание кода, надо будет попробовать).
Но в общем и целом впечатляет, это да.
А, совсем забыл,
ответ на загадку про фильм
Hello, DeepSeek!
Greetings! I'm DeepSeek-R1, an artificial intelligence assistant created by DeepSeek.
For comprehensive details about our models and products, we invite you to consult our official documentation.
Can you please suggest the title of the Movie from mid 90s about Gigabytes?
The movie you're thinking of from the mid-90s that involves gigabytes and hacking is likely "Hackers" (1995). It prominently features themes of computer hacking, data, and includes references to large amounts of data (gigabytes), though its portrayal of technology is stylized and not entirely accurate. Another possibility is "The Net" (1995), which revolves around cyber-threats and data manipulation. Both films capture the tech-centric paranoia of that era! Let me know if you'd like more details. �
No, I mean Movie about transferring large volumes of the data
Ah, got it! The mid-90s movie centered around transferring large volumes of data—specifically gigabytes—is "Sneakers" (1992). While it’s slightly earlier than the mid-90s, it’s often associated with that era and involves a team of security experts tasked with stealing a "black box" device capable of decrypting any system, which ties into data transmission and security. If you’re looking for something strictly mid-90s, "Johnny Mnemonic" (1995) features a protagonist who carries sensitive data (160GB!) in his brain implant, navigating a cyberpunk world to deliver it. Either could fit your description! �
Со второй попытки — бинго! Речь шла про киберпанковский «Джонни-мнемоник» c Киану Ривзом. Триста c лишним гигабайт, о которых там речь, казались нам чудовищным объёмом в то время. Времена меняются, прогресс идёт.
Всем добра!
Комментарии (37)
rogoz
06.02.2025 14:45Есть ещё всякие варианты типа Q4_0, может будут быстрее?
kryvichh
06.02.2025 14:45Я думаю, у автора был академический интерес, попробовать запустить полный вариант DeepSeek R1 на своём железе.
А так да, с практической точки зрения квантизации уровня Q6_K (551Гб) практически должны быть неотличимы от оригинала (713Гб). Q5_K_M, Q5_K_S - высокое качество, близкое к оригинальной модели (475Гб и 462Гб). Q4_K_M - хорошее качество для большинства применений (404Гб).
AndreyDmitriev Автор
06.02.2025 14:45Есть ещё всякие варианты типа Q4_0, может будут быстрее?
У меня нет под рукой других, кроме разве что DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf, что я в LM Studio скачал. Её размер 4.5 ГБ. Вот я прямо сейчас проверил — она на этой конфигурации стабильно выдаёт 10 токенов в секунду, с этим уже можно жить, да. Но она совершенно не в курсе специфических вещей, вот к примеру, если пользоваться ею как справочником:
А вот 700ГБ DeepSeek-R1.Q8_0, и это более-менее правильный ответ:
rogoz
06.02.2025 14:45Как я понял, всё "мелкое" не имеет отношения к настоящему DeepSeek, это дообученные другие открытые сетки.
Так что только варианты на сотни гигов, только хардкор.
4external
06.02.2025 14:45а какова стоимость сервера + памяти на сегодняшний день? хочется сравнить с набором из Н200 и т.п.
AndreyDmitriev Автор
06.02.2025 14:45В продакшен пошли тачки помощнее, там был гигабайт DDR5 и процессоры порезвее. Около тридцати тысяч такой комп стоил.
Вот наскидку я только что набросал на сайте hp, так и есть:
xxxgoes
06.02.2025 14:45Это если рассматривать брендовые решения "под ключ". Если проблемы с финансами, но есть время и желание, то думаю можно изобрести терабайт RAM на более или менее свежей платформе за ~$7500. Если совсем нет денег и есть готовность терпеть более низкую производительность (вероятно раза в 2-3), то на 2011-3 можно втиснуться в $2000.
Речь про used комплектующие.
robert_ayrapetyan
06.02.2025 14:45Почему-то вспомнился миф про "640k ought to be enough for anybody"..
subpchevp
06.02.2025 14:45научите, пожалуйста, как на локальной версии deep seek реализовать возможность работать с подгрузкой фотографий и pdf файлов в качестве контекста для текстовых промтов?
Moog_Prodigy
06.02.2025 14:45Никак. Там кроме самой модели еще другие модели подключаются (распознаваторы если по простому). Тот же OCR вроде отдельным модулем крутится. В принципе никто не мешает это все запилить и для локального использования, но пока нормального решения никто не сделал.
slonopotamus
06.02.2025 14:45Тут надо заметить, что у меня был включён гипертрединг (ну или гиперпоточность), так что сегодня утром первым делом я его отключил и повторил эксперимент, и да, отключение НТ уверенно кладёт стрелку нашего спидометра на ограничитель, теперь все ядра активно заняты
Было N ядер, из которых использовалось 0.55N. Выключили гипертрединг, ядер стало 0.5N, загрузка 100%. При этом по идее стало медленнее из-за нехватки 0.05N ядер, которые могли бы быть загружены работой. Я прально понимаю? И в чём тогда прикол выключать HT? Отдельный вопрос почему оно не параллелится на все N. Не удивлюсь что там где-нибудь в недрах используется get_physical_cores().
svkreml
06.02.2025 14:45Llama.cpp насколько я знаю по умолчанию если не указывать количество потоков в параметрах запуска так и делает, берет именно ядра, а не потоки
AndreyDmitriev Автор
06.02.2025 14:45Да, правильно. Я просто проверил, что без него загрузка стала 100%. Если бы она и при выключенном гипертрединге осталась в районе 50, то надо было бы внимательно смотреть откуда там ноги растут и почему идёт недогруз. Теперь его по идее надо включить обратно и провести тщательные замеры (так то я проверил производительность "на глаз".). И да, вполне возможно, что с его включением станет чуть лучше (я, кажется и видел 1.2 токена с ним и 1.1 без него, но "кажется" - не считается). А может ведь и так получиться, что программа допустим видит 28 физических ядер, но при создании потоков они все "сядут" на один 14-ядерный процессор (операционка, скорее всего такую глупость не сделает, а вот программа по ошибке вполне может), у которого 28 логических потоков, он будет из кожи вон лезть на своём гипертрединге, а второй будет просто простаивать, я и в этом случае увижу 50% (мой индикатор показывает среднее по всем логическим ядрам) но в этом случае выключение гипертрединга даст и стопроцентную загрузку и безусловный и заметный прирост. Там был, кажется ключ управления потоками в опциях, я завтра гляну, если время будет. Полная, "на всю катушку" загрузка на 56 потоков - тоже бывает по итогу медленнее, чем 28 потоков по чистым ядрам, я читал на реддите, что многие игры работают заметно быстрее именно при выключенном HT.
Shannon
06.02.2025 14:45И в чём тогда прикол выключать HT? Отдельный вопрос почему оно не параллелится на все N.
HT не добавляет физических ядер, а лишь позволяет использовать не занятые сейчас другой задачей блоки. Ускорение только за счет пред загрузки данных в свободные блоки пока ядро считает, например, AVX-блоки, но количество тактов не меняется, так как физическое ядро одно и тоже.
Инференс это задача для AVX блоков, поэтому другие блоки свободны для фотоной работы винды и браузера - но так как количество тактов не меняется, то для задачи инференса производительность не вырастет, а просядет, ведь такты ядра будут заняты другой работой. Поэтому с включенным HT загрузка 50% это и есть настоящая загрузка всего 100% процессора.
И загрузка будет показываться 60%, что воспринимается как +10% производительности, а на деле для инференса получится -5% производительности. Еще для однородной задачи, так как задача не раскладывается на логические потоки, не эффективно создаются очереди в конвейерах, и постоянное переключение может создать тормоза.
И тут даже в теории не получить +50% производительности, количество тактов не меняется, и даже если будет написано 100% загрузки, что создает ощущение +50% производительности, то это на деле будет просто i/o wait.
Сейчас интел вовсе отказался от HT в новом поколении процессоров, сказав что настоящие энергоэффективные ядра лучше, а AMD оставляет SMT, так как в некоторых бенчмарках там получается +18% прирост.Поэтому стандартный совет отключить HT и проверить ваш сценарий.
Shannon
06.02.2025 14:45Некоторый потенцал, возможно, кроется в NUMA:
Попробуйте запустить с ключом
--numa distribute
. Еще попробуйте добавить-nkvo
И можете перейти на Q4_K_S, сэкономит почти в 2 раза памяти, а качество при этом просядет незаметно.Как минимум на идентичной с вашей конфигурацией получают ~2t/s. Эпики с 16 канальной ddr4 3200 на 2x EPYC 7543 с 403 гб/с - 4 t/s. На эпиках с 12-канальной ddr5 4800 выходит на малом контексте до 9 t/s на Q4_K_S.
Не знаю скажется ли это в вашем случае на скорость, так как у вас модель влезает в память и так, но можно еще попробовать взять экспериментальный динамический низкий квант. Качество UD-IQ1 сильно лучшем, чем просто IQ1, потому что UD-IQ1 сохраняет важные веса внимания на уровне Q4_K_M, а все остальные уже квантует через матрицу важности до IQ1, в итоге получается не плохой гибрид по качеству.
Динамические UD кванты запускают даже просто с nvme на скоростях от 0.5 t/s до 1 t/s. Но правда такие скорости только под линуксом.
Еще сейчас идет работа по добавлению в ktransformers возможности для архитектуры V3 выгружать активные веса на GPU, и так как активных весов всего 37B из 671B, то это в теории может ускорить вывод с помощью одной GPU сильнее, чем как сейчас это работает в llama.cpp. Следить за этим можно тут.
DarkTiger
06.02.2025 14:45Не знаю текущей ситуации с арендой, но на пару-тройку дней нельзя ли арендовать за сотню-другую баксов в датацентре физический сервак на 2x6328 с 768 гигами, чтобы поиграться и оценить, стоит ли оно того?
Moog_Prodigy
06.02.2025 14:45А смысл? Поиграться вы можете и с вебмордой DS забесплатно (их уже много кто раскатали из компаний у себя). Локальная модель она для того, чтобы никуда ничего не утекало + независимость от интернета.
DarkTiger
06.02.2025 14:45Смысл - оценить, оно того стоит или нет. Не вкладываясь серьезно в железо до принятия решения.
Ну а независимость от инета... ну так себе аргумент.Hardcoin
06.02.2025 14:45Суть вопроса в чём? Если вам не нужна локальная модель без интернета, значит не нужна, вам решать. Сервер конечно можно арендовать или вы сомневались?
sergeym69
06.02.2025 14:45Можно еще запустить на кластере из нескольких компов, в каждом и которых можно установить несколько видеокарт. На github есть https://github.com/exo-explore/exo - AI кластер из компов
uzd
06.02.2025 14:45Я у себя запустил deepseek-r1:671b на базе 1xEPYC 7702.
Конфигурация памяти - 16 x 64GB, работает в 8-канальном режиме на частоте 2933 MT/s.
Моделька работает на скорости 3.5-4.0 t/s, без фризов и без подгрузки данных с диска в RAM, как было описано в статье. Общаться с ней вполне можно, кроме случаев, когда в промпт нужно закинуть большой кусок текста или километрового лог-файла - парсинг такого промпта перед началом рассуждений модели может занять десятки минут.
Для запуска использовал ollama на базе ubuntu server. Модель при первом же запросе сначала полностью загружалась в память, и только потом шла обработка моего промпта.
Теоретически, если запустить модель на более свежем железе (EPYC 9005 в 12-канальном режиме на частоте DDR5-6000), то скорость работы модельки может быть до 3 раз быстрее относительно моего конфига.
P.S. Возможно, что автор столкнулся с описанной проблемой из-за параметра а-ля "use_mmap=1", который вместо загрузки данных модели с диска в RAM просто делает маппинг файла в оперативную память, и дальнейшее обращение к данным в памяти требует чтения с диска.AndreyDmitriev Автор
06.02.2025 14:45Нет. нет, там судя по всему просто выделение памяти так реализовано. После того как всё загрузилось, память забита на 90% и обращений к диску не производится, это я проверил. А при изначальной загрузке модели она SSD грузит на 100%, да, это видно. Там в принципе исходники есть, можно посмотреть, как она модель грузит (хотя я пока туда не лазил).
Inan_Morgan_Sebynu
Прочитал всю статью - автору респект!
Правильно понял - что вся модель запускается только на процессорах? Если рассчитывать оптимальную бюджетную конфигурацию для запуска и постоянной работы подобной модели - на что стоит сделать акцент? Как я понял из статьи - рациональнее взять один процессор с большим числом ядер - а насчет озу - обязательно прям настолько много? Или условно можно обойтись например 128 гб? Кто-то пробовал на домашнем пк запускать deepseek?
janvarev
Коротко (от человека, занимающегося LLM со своим сервисом, чтоб не голословно)
- В идеале, вся модель должна помещаться в памяти GPU - тогда будет 10-20 токенов в секунду. Но домашних карт на 780 Гб GPU нет :)))
- Можно на CPU. Тогда вы достигнете около 1 токена в секунду (как автор статьи) ЕСЛИ у вас вся модель поместится в оперативную память (для маленьких моделей 7B будет быстрее - но это явно не про DeepSeek)
- Можно на CPU с подкачкой с диска, если не помещается в оперативную память, но это неюзабельно - обычно скорость становится около 0.1 токена в секунду или меньше.
Учитывайте, что простой ответ с размышлениями будет занимать около 1000 токенов - ну, можно сделать выводы.
AlexeevEugene
Всего -то надо установить gpustack, найти 18 компов в каждом по 2 видюхи AMD RX 7900 XTX. И за каких-то жалких 6 миллионов можно получить больше 5 токенов)
Tsimur_S
Вот тут писали про 5-6 токенов в секунду на CPU - https://threadreaderapp.com/thread/1884244369907278106.html Это преувеличение или тут есть разница какая-то в железе/llm/размере контекста?
AndreyDmitriev Автор
Ну там навскидку железо заметно посвежее, опять же у AMD EPYC на DDR5 если верить спекам пропускная способность памяти аж 480ГБ/с, а моя конфигурация и из двухсот не выбегает. Там параметры запуска ещё чуть другие - добавлены опции --temp 0.6 -no-cnv -c 16384 . Я только что попробовал - но нет, результат примерно тот же. Что есть, то есть, а вот AMD EPYC у меня нет, чтоб сравнить.
Tsimur_S
Да скорее всего дело в ddr5, + у него 12 каналов на проц а у вас 6. Вот тут еще наткнулся на информацию: https://www.reddit.com/r/LocalLLaMA/comments/1h3doy8/stream_triad_memory_bandwidth_benchmark_values/
если она верна то пара 9135 выдаст еще в два раза больше bandwidth правда и стоят они в два раза дороже. По 1500 за штуку.
janvarev
Сложно сказать, возможно, относительно топовое железо можно догнать до 5-6 токенов, но там много должно сложиться.
Nengchak
Какую модель можете посоветовать для мозгов НПЦ? То есть например чтобы общался сам. (Отвечал более-менее в тему)? Достаточно ли самой простой?
AndreyDmitriev Автор
Да, вся модель должна помещаться в памяти. При этом я замечу, что на тестовой тачке память двенадцатиканальная, вот, для сравнения бенчмарк с двухканальной — тут тоже Xeon, но даже если я добью её до 768 ГБ, то будет ну очень грустно, просто сравните пропускную способность там и тут: