CPU 混合推理,非常見大模型量化方案:“二三五六” 位量化

本篇文章聊聊網上聊的比較少的具體量化操作,非常見整型位數的量化,來自讓各種開源模型能夠在 CPU 環境、CPU & GPU 環境混合推理的技術方案:llama.cpp 。

寫在前面

接下來,有計劃分享一些關于各種開源模型的實踐內容。為了能讓更多的同學能夠玩起來,降低入門的硬件門檻還是很有必要的。模型量化技術就是這樣一個“神奇、有效”的方案。

看過前兩篇文章《零一萬物模型折騰筆記:官方 Yi-34B 模型基礎使用》、《本地運行“李開復”的零一萬物 34B 大模型》的同學知道,類似 34B 的模型,如果想不怎么量化直接跑起來,大概需要 76~85GB 的顯存。如果我們進行效果損失比較小的 8 位量化,那么也需要 46GB 左右,如果是 4 位量化模型,那么也需要 21GB 左右的顯存。

雖然模型能跑了,但是有可能模型效果“打了骨折”

是的,模型的量化其實就是這樣的一個,把類似我們相機拍攝照片(RAW),轉換成“PNG”,再轉換成“JPG”,最后甚至轉換成“GIF”的過程。我們追求的是盡量省錢,在我們的設備上保持最好效果的將模型跑起來。盡量整個接近 “PNG” 的 “JPG”,而不是一定要折騰個 “GIF” 。

尤其是一般情況下,許多同學會使用八位(INT8)或者 四位(INT4)位量化,但是我們很容易會遇到兩個尷尬的情況:

  • 有的模型量化成四位(INT4)效果變的不是很好,但是量化成八位(INT8)效果還行。可是八位(INT8)尺寸又太大,運行不太方便,希望模型尺寸能夠小一些。
  • 有的模型量化成四位(INT4),模型還是太大,硬件跑不起來或者跑起來太費力,希望模型變的更小巧一些。

在今年早些時候的幾篇文章和對外分享里,我曾經多次提到了幾種不同的模型量化方案,包括 Transformers、GGML 等,感興趣的同學可以自行翻閱,就不多贅述了。

本篇文章,我們主要來聊聊非常見整型位數的模型量化方案。用自己制作的量化程序,將原本在本地用游戲顯卡跑不起來的 YI 34B 模型跑起來。

準備材料

關于模型量化需要準備兩個素材,一個是模型,另外一個是量化使用的計算設備。

模型程序文件

任意參數量的模型,可以是 7B、13B、14B、20B、33B、34B、68B、70B …的模型,也可以是更小參數量的小尺寸的模型。

我這里使用的是零一萬物開源的 YI-34B 的社區 finetune 微調訓練的版本,通常情況下,社區可能有熱門模型的量化版本,經常看到一些同學說“等個量化版本”。

但其實自己動手,豐衣足食。況且,即使是從社區下載量化版本,模型體積也很大,需要來來回回測試模型是否合適,重復下載也非常消耗時間和寬帶成本,遠不如自己量化來的方便。

關于模型程序下載,方法很多。如果你想要從 HuggingFace 相對快速下載模型,可以參考這篇文章中的 “模型程序下載” 來解決問題。

量化使用的硬件

而量化模型使用的硬件,需要 CPU 計算能力相對強一些的機器,如果你有 GPU,那么將會極大的提升模型量化速度,如果沒有也沒有關系。

至于量化后的產物,則是各種設備通用的,你可以在 Windows 量化后給 Linux 或者 macOS 設備使用。你也可以使用有 CPU 和 GPU 的設備,量化后給只有 CPU 的設備使用。

唯一有一些差異的,只有運行這個通用模型格式程序的啟動程序,是需要和你當前的運行環境和操作系統有些關聯的,比如需要構建,或者安裝時需要一些初始化。

相比較模型,程序這個真的就是小意思啦。

模型的 GGUF (GGML Universal File)格式量化準備

GGUF 是 GGML 的全新替代型,被稱為 GGML 通用文件格式。

GGUF 支持的模型量化格式非常多,刨除“幾種跨開源生態模型轉換的場景外”,主要依賴兩個程序:convert.pyquantize 程序。前者以 Python 腳本的形態存在于 llama.cpp 項目的目錄中,后者需要我們進行項目的構建。

下載 llama.cpp 的代碼,然后就能夠進行構建操作啦:

# 下載代碼
git clone https://github.com/ggerganov/llama.cpp.git
# 切換工作目錄到項目文件夾內
cd llama.cpp
# 構建項目可執行文件(有顯卡)
make -j LLAMA_CUBLAS=1
# 構建項目執行文件 (沒有顯卡)
make -j

等待程序構建完畢,所有的準備工作就都完成啦。

預轉換:Convert.py 轉換腳本

這個腳本能夠將非 GGML 格式的文件轉換為 GGML,以 GGUF 后綴進行保存。程序默認支持轉換下面幾類格式的模型:*.pth*.pt*.bin*.safetensors

是我們進行后續非常見整型模型量化的基礎操作步驟。

如果我們只追求使用 8 位量化的,可以使用 CPU 和 GPU 混合推理的模型,那么我們可以參考這篇文章中的“嘗試對模型進行幾種不同的量化操作”的方法中的命令行參數,將模型轉換為 GGML 的 q8_0 模型。

但如果,我們希望制作更多其他的不同的類型的模型,比如 2 位量化~ 6 位量化,那么我非常建議大家使用 convert.py 腳本制作和轉換一個 f16 類型的 GGML 模型。

雖然程序的命令行參數看起來很麻煩,但是我們需要使用到的轉換命令其實非常簡單,使用 Python 調用程序,命令中攜帶“模型路徑”和“輸出的模型類型”即可:

python ./convert.py 【模型的路徑】 --outtype f16

我這里以 YI-34B 的社區 finetune 模型 brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties 為例子,調整為我自己的模型存放路徑:

python ./convert.py ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/ --outtype f16

執行命令后,機器將會火力全開的進行程序編譯,輸出大量日志:

Loading model file ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/model-00001-of-00008.safetensors
Loading model file ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/model-00001-of-00008.safetensors
Loading model file ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/model-00002-of-00008.safetensors
...params = Params(n_vocab=64000, n_embd=7168, n_layer=60, n_ctx=200000, n_ff=20480, n_head=56, n_head_kv=8, f_norm_eps=1e-05, rope_scaling_type=None, f_rope_freq_base=5000000.0, f_rope_scale=None, n_orig_ctx=None, rope_finetuned=None, ftype=<GGMLFileType.MostlyF16: 1>, path_model=PosixPath('../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties'))
Loading vocab file '../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/tokenizer.model', type 'spm'
Permuting layer 0
Permuting layer 1
Permuting layer 2
...model.embed_tokens.weight                        -> token_embd.weight                        | BF16   | [64000, 7168]
model.layers.0.input_layernorm.weight            -> blk.0.attn_norm.weight                   | BF16   | [7168]
...Writing ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/ggml-model-f16.gguf, format 1
gguf: This GGUF file is for Little Endian only
gguf: Setting special token type bos to 1
gguf: Setting special token type eos to 2
gguf: Setting special token type unk to 0
gguf: Setting special token type pad to 0
[  1/543] Writing tensor token_embd.weight                      | size  64000 x   7168  | type F16  | T+   1
[  2/543] Writing tensor blk.0.attn_norm.weight                 | size   7168           | type F32  | T+   2
[  3/543] Writing tensor blk.0.ffn_down.weight                  | size   7168 x  20480  | type F16  | T+   2
...Wrote ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/ggml-model-f16.gguf

當一切都結束后,我們能夠看到類似上面日志的最后一行提示,告訴我們轉換好的模型名字和存放到機器的什么位置了。默認會存放于你指定要轉換模型的目錄,并以 .gguf 后綴保存文件。

最終轉換:quantize 量化程序

當我們使用上面的方法,將模型轉換為了相對高精度的模型文件后,我們就可以進行下一步量化了。

執行 ./quantize --help,除了程序的執行命令格式參考外,我們還能夠看到量化程序支持的所有類型:

Allowed quantization types:2  or  Q4_0   :  3.56G, +0.2166 ppl @ LLaMA-v1-7B3  or  Q4_1   :  3.90G, +0.1585 ppl @ LLaMA-v1-7B8  or  Q5_0   :  4.33G, +0.0683 ppl @ LLaMA-v1-7B9  or  Q5_1   :  4.70G, +0.0349 ppl @ LLaMA-v1-7B10  or  Q2_K   :  2.63G, +0.6717 ppl @ LLaMA-v1-7B12  or  Q3_K   : alias for Q3_K_M11  or  Q3_K_S :  2.75G, +0.5551 ppl @ LLaMA-v1-7B12  or  Q3_K_M :  3.07G, +0.2496 ppl @ LLaMA-v1-7B13  or  Q3_K_L :  3.35G, +0.1764 ppl @ LLaMA-v1-7B15  or  Q4_K   : alias for Q4_K_M14  or  Q4_K_S :  3.59G, +0.0992 ppl @ LLaMA-v1-7B15  or  Q4_K_M :  3.80G, +0.0532 ppl @ LLaMA-v1-7B17  or  Q5_K   : alias for Q5_K_M16  or  Q5_K_S :  4.33G, +0.0400 ppl @ LLaMA-v1-7B17  or  Q5_K_M :  4.45G, +0.0122 ppl @ LLaMA-v1-7B18  or  Q6_K   :  5.15G, -0.0008 ppl @ LLaMA-v1-7B7  or  Q8_0   :  6.70G, +0.0004 ppl @ LLaMA-v1-7B1  or  F16    : 13.00G              @ 7B0  or  F32    : 26.00G              @ 7BCOPY   : only copy tensors, no quantizing

這里,我建議始終使用 Q4_KQ5_K 這類代指名稱來進行模型轉換,并且在進行轉換之前,偶爾執行 ./quantize --help 看看有沒有新的、更適合你的量化方案。名稱中的 Q數字 中的數字就是對應的量化的位數啦。

一般來說,位數越高,需要的內存和顯存就越多,運行起來越慢,但是效果和精度就越接近原始版本。反之,我們雖然得到了省資源的版本,但是效果會有明顯的降低。不過,如果你模型跑不起來,效果是零,這種情況下能夠量化跑起來的模型,總歸是比沒有強,某種程度來說,也是不得已而為之。

幫助信息中展示的如何使用命令行的演示信息,同樣是內容比較多比較復雜的。但是同樣的,我們實際只需要非常簡單的使用方法,記住下面的調用方式就足夠了:

./quantize 【模型地址】【模型類型名稱】

如果我們將命令中的“變量”進行替換,改成本文中我使用的模型和我選擇的量化方案,命令行如下:

./quantize ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/ggml-model-f16.gguf Q5_K_M

命令執行過程中,我們將看到滾動的日志:

ggml_init_cublas: GGML_CUDA_FORCE_MMQ:   no
ggml_init_cublas: CUDA_USE_TENSOR_CORES: yes
ggml_init_cublas: found 1 CUDA devices:Device 0: NVIDIA GeForce RTX 4090, compute capability 8.9
main: build = 1622 (8a7b2fa)
main: built with cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 for x86_64-linux-gnu
main: quantizing '../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/ggml-model-f16.gguf' to '../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/ggml-model-Q5_K_M.gguf' as Q5_K_M
llama_model_loader: loaded meta data with 20 key-value pairs and 543 tensors from ../brucethemoose/CapyTessBorosYi-34B-200K-DARE-Ties/ggml-model-f16.gguf (version GGUF V3 (latest))
llama_model_loader: - tensor    0:                token_embd.weight f16      [  7168, 64000,     1,     1 ]
llama_model_loader: - tensor    1:           blk.0.attn_norm.weight f32      [  7168,     1,     1,     1 ]
...
llama_model_loader: - tensor  542:               output_norm.weight f32      [  7168,     1,     1,     1 ]
llama_model_loader: Dumping metadata keys/values. Note: KV overrides do not apply in this output.
llama_model_loader: - kv   0:                       general.architecture str              = llama
llama_model_loader: - kv   1:                               general.name str              = brucethemoose
llama_model_loader: - kv   2:                       llama.context_length u32              = 200000
llama_model_loader: - kv   3:                     llama.embedding_length u32              = 7168
...
[ 541/ 543]               blk.59.ffn_down.weight - [20480,  7168,     1,     1], type =    f16, quantizing to q6_K .. size =   280.00 MiB ->   114.84 MiB | hist: 
[ 542/ 543]               blk.59.ffn_norm.weight - [ 7168,     1,     1,     1], type =    f32, size =    0.027 MB
[ 543/ 543]                   output_norm.weight - [ 7168,     1,     1,     1], type =    f32, size =    0.027 MB
llama_model_quantize_internal: model size  = 65593.31 MB
llama_model_quantize_internal: quant size  = 23193.68 MBmain: quantize time = 99803.07 ms
main:    total time = 99803.07 ms

轉換完畢,我們前往模型的目錄,查看文件大小,能夠看到非常明顯的尺寸縮減:

# du -hs *
23G	ggml-model-Q5_K_M.gguf
65G	ggml-model-f16.gguf

至于模型的使用,就太簡單啦。

我們可以使用 llama.cpp 項目中的 mainserver 來運行模型,前者會在命令行中啟動一個交互式的終端,后者則會啟動一個簡潔的 Web UI,我們在瀏覽器中就可以輕松的調節模型的調用參數。

在前兩篇相關的文章中有提到過,這里我們再聊一次,順便聊聊不同的參數的選擇和調整策略。

我一般的“起手式”是這樣:

./server --ctx-size 2048 --host 0.0.0.0 --n-gpu-layers 50 --model ../playground/01-ai/Yi-34B/ggml-model-q8_0.gguf

上面的命令中,分別包含了:

  • --ctx-size” 指定模型會話窗口大小,所能容納和使用的 Token 數量,這里如果想省點顯存和內存,就設置小一些,能夠滿足你的任務需要就好。如果資源比較多,可以開到模型的上限,比如最近的默認模型都是 4k 的,就設置 4096,8K 就設置 8192,200K 就設置個 200000,以此類推。
  • --host” 默認其實可以不添加,但是如果你在局域網,或者你的服務運行在容器里,那么你需要分享或者在容器外訪問,設置 --host 0.0.0.0 就很有必要啦。
  • --n-gpu-layers” 這個參數需要配合顯卡一起使用,如果你有顯卡,但是顯卡裝不下模型,或者裝下模型后快滿了,可以考慮適當調整下數值,根據自己的需求,將合適的模型層數扔到顯卡里,稍微給顯卡留點富余量。扔到顯卡里的模型層數越多,推理速度越快。
  • --model” 這個參數沒有什么特別的,指定我們下載或者轉換好的 GGML 模型文件就好。

好啦,當這個命令執行后,我們就能夠快樂的和模型一起玩耍啦。

使用量化后的 Yi-34B 進行角色扮演游戲

是不是很有趣,后面有機會我們聊聊上面這個交互體驗是如何實現的。

最后

這篇內容就先寫到這里,接下來的相關文章,我們來聊聊社區里不同優化方向和模型的模型們。

希望大家玩模型,都能玩的開心。感謝所有為開源模型辛苦工作的模型創作者團隊,和所有為開源社區搖旗吶喊,將好的東西分享給更多的人的朋友們。

–EOF


本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或重新修改使用,但需要注明來源。 署名 4.0 國際 (CC BY 4.0)

本文作者: 蘇洋

創建時間: 2023年12月12日
統計字數: 8528字
閱讀時間: 18分鐘閱讀
本文鏈接: https://soulteary.com/2023/12/12/cpu-hybrid-inference-unusual-large-language-model-quantization-2-3-5-6-bit-quantization.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215294.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215294.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215294.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安裝ThingBox Eclipse Plugin

1. ChatGPT問 The latest version of the ThingBox Eclipse Plugin requires Eclipse IDE 2021-06 or later. 2. PTC官網下載 MED-61378-CD-092_F000_Eclipse-Plugin-9-0-1.zip文件, 和 MED-61098-CD-085_F000_ThingWorx-Extension-SDK-8-5-0&#xff08;需要賬號&#xff09…

虛擬化邏輯架構:KVM虛擬機通過OVS端口組實現網絡連接

目錄 一、實驗 1.CentOS 7 安裝 OpenVSwitch(構建RPM安裝包&#xff09; 2.KVM虛擬機通過OVS端口組實現網絡連接 二、問題 1.安裝openvswitch-2.5.10報錯 2.virt-install未找到命令 3.如何刪除自定義網絡 一、實驗 1.CentOS 7 安裝 OpenVSwitch(構建RPM安裝包&#xff…

字符串知識點

一. 1.字符占據一個字節 2.字符數組&#xff1a;char name[15] { W, a, n, g, L, i}; 字符串&#xff1a;char name[15] “Wang Li”&#xff1b; 二. 1.字符串&#xff1a;為有效長度&#xff08;有效字符的個數&#xff09;而不是字符數組的長度&#xff1b; 2.&#…

創建一個有陰影的threejs三維幾何體

import * as THREE from "three" import { OrbitControls } from three/examples/jsm/controls/OrbitControlsconst width window.innerWidth; const height window.innerHeight;//創建場景 const scene new THREE.Scene(); scene.background new THREE.Color(#6…

LinuxBasicsForHackers筆記 --Python 腳本基礎

添加Python模塊 Python 有一個專門用于安裝和管理 Python 包的包管理器&#xff0c;稱為 pip&#xff08;Pip Installs Packages&#xff09;。由于我們在這里使用 Python 3&#xff0c;因此您將需要 Python 3 的 pip 來下載和安裝軟件包。默認情況下應包含 Pip&#xff0c;但…

學習Node.js與Webpack總結

今天學習了模塊化的簡介&#xff0c;其實一個項目是由很多個模塊文件組成的&#xff0c;它們有它們各自的功能和用途來協助這個項目的完成&#xff0c;這樣的模塊組成有很多的好處比如提高代碼的復用性、還可以按需加載、還有獨立的作用域&#xff0c;還需要搞清楚的一點就是No…

如何截取Hive數組中的前N個元素?

文章目錄 1、需求描述2、使用索引3、使用posexplode()4、轉換為字符串操作 1、需求描述 需求&#xff1a;截取任意給定數組中的前N個元素&#xff0c;返回截取后的子數組 假設我們有如下三種類型的Hive數組&#xff1a; select array(1,2,3,4) -- [1,2,3,4] selec…

vue前端訪問Django channels WebSocket失敗

現象 前端報錯&#xff1a;SSH.vue:51 WebSocket connection to ‘ws://127.0.0.1:8000/server/terminal/120.59.88.26/22/1/’ failed: 后端報錯&#xff1a;Not Found: /server/terminal/120.79.83.26/22/1/ 原因 django的版本與channels的版本不匹配&#xff08;django…

關于個人職業選擇

職業選擇&#xff0c;一直是個老生常談的話題。這并不是一個容易做的決定。 讓我們來看看AI怎么說。 首先是方向性的回答&#xff1a; 然后是一些具體的回答 我個人比較傾向于深耕網絡安全。這是一個很有趣也是一個持續發展著的領域。 不知道關于這個事情你怎么看&#xff0…

在線學習平臺-課程分頁、用戶管理、教師查詢

在線學習平臺------手把手教程&#x1f448; 用戶管理 添加功能增強 新增屬性 若依里的用戶模塊(SysUser)是沒有課程這一屬性的,要實現我們自己的課程分頁查詢功能 這個位置傳入的實體類SysUser要加上classId,記得加上get、set方法 更改sql語句 ctrl 鼠標左鍵不斷點進去…

DS二叉排序樹之刪除

Description 給出一個數據序列&#xff0c;建立二叉排序樹&#xff0c;并實現刪除功能 對二叉排序樹進行中序遍歷&#xff0c;可以得到有序的數據序列 Input 第一行輸入t&#xff0c;表示有t個數據序列 第二行輸入n&#xff0c;表示首個序列包含n個數據 第三行輸入n個數據…

藍橋杯周賽 第 1 場 強者挑戰賽 6. 小球碰撞【算法賽】(思維題/最長上升子序列LIS)

題目 https://www.lanqiao.cn/problems/9494/learning/?contest_id153 思路來源 Aging代碼 題解 二分時間t&#xff0c;第i個小球對應一個起點pi、終點pit*vi的區間&#xff0c;問題轉化為&#xff0c; 選最多的區間&#xff0c;使得不存在區間包含&#xff08;即li<l…

微信小程序過濾器之計算當前時間差

微信小程序過濾器之計算當前時間差 前言一、wxs簡介二、使用步驟1.定義2.使用 前言 最近遇到了一個需求&#xff0c;將小程序里面的具體時間2023-12-11 09:41:06轉為當前時間差10小時前&#xff0c;這塊可以使用js邏輯函數對數據進行處理&#xff0c;但這里我們采用微信小程序…

Error: Failed to resolve vue/compiler-sfc——vite項目啟動報錯——npm run serve

運行項目時&#xff0c;報錯如下&#xff1a; Error: Failed to resolve vue/compiler-sfc 根據報錯信息的提示&#xff1a;vue的版本必須大于3.2.25&#xff0c;經過查看package.json文件&#xff0c;可以看到vue的版本為3.2.36&#xff0c;是滿足條件的。 因此考慮緩存問題&…

【OPNEGIS】Geoserver原地升級jetty,解決Apache HTTP/2拒絕服務漏洞 (CVE-2023-44487)

Geoserver是我們常用的地圖服務器&#xff0c;在開源系統中的應用比較廣泛。在實際環境中&#xff0c;我們可能會選用官方的二進制安裝包進行部署&#xff0c;這樣只要服務器上有java環境就可以運行&#xff0c;方便在現場進行部署。 1.問題來源 這次由于甲方一月一次的漏洞掃…

Mysql表的數據類型

數據類型 https://www.sjkjc.com/mysql/varchar/ MySQL 中的數據類型包括以下幾個大類&#xff1a; 字符串類型 數字類型 日期和時間類型 二進制類型 地理位置數據類型 JSON 數據類型 MySQL 字符串數據類型 VARCHAR&#xff1a;純文本字符串&#xff0c;字符串長度是可變的…

智能優化算法應用:基于陰陽對算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用&#xff1a;基于陰陽對算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用&#xff1a;基于陰陽對算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.陰陽對算法4.實驗參數設定5.算法結果6.參考文…

云計算、邊緣計算、霧計算

目錄 云計算邊緣計算霧計算 云計算 云計算是基于互聯網的計算模式&#xff0c;允許用戶通過網絡獲取計算資源、存儲資源、數據庫等服務&#xff0c;無需了解和管理底層 云計算是分布式計算的一種&#xff0c;指的是通過網絡“云”將巨大的數據計算處理程序分解成無數個小程序…

Java - Mybatis的緩存機制、集成SpringBoot后緩存相關問題

mybaits提供一級緩存&#xff0c;和二級緩存 一級緩存&#xff08;默認開啟&#xff09; 一級緩存是SqlSession級別的緩存。在操作數據庫時需要構造 sqlSession對象&#xff0c;在對象中有一個(內存區域)數據結構&#xff08;HashMap&#xff09;用于存儲緩存數據。不同的sqlSe…

STM32F407-14.3.1-01 時基單元

時基單元 可編程高級控制定時器的主要模塊是一個 16 位計數器及其相關的自動重載寄存器。計數器可遞增計數、遞減計數或交替進行遞增和遞減計數。計數器的時鐘可通過預分頻器進行分頻。 計數器、自動重載寄存器和預分頻器寄存器可通過軟件進行讀寫。即使在計數器運行時也可執行…