七天入门大模型 :大模型量化及低成本部署最佳实践

图片
七天入门大模型已完成了5篇,喜欢记得收藏、关注、点赞。

  • 七天入门大模型 :LLM大模型基础知识最全汇总
  • 七天入门大模型 :提示词工程 Prompt Engineering,最全的总结来了!
  • 七天入门大模型 :LLM和多模态模型高效推理实践
  • 七天入门大模型 :大模型LLM 训练理论和实战最强总结!
  • 七天入门大模型 :大模型自动评估理论和实战

技术交流群

前沿技术资讯、算法交流、求职内推、算法竞赛、面试交流(校招、社招、实习)等、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企开发者互动交流~

我们建了NLP&大模型面试与技术交流群, 想要进交流群、需要源码&资料、提升技术的同学,可以直接加微信号:mlc2060。加的时候备注一下:研究方向 +学校/公司+CSDN,即可。然后就可以拉你进群了。

方式①、微信搜索公众号:机器学习社区,后台回复:加群
方式②、添加微信号:mlc2060,备注:技术交流

模型的量化

前文中我们提到,模型的推理过程是一个复杂函数的计算过程,这个计算一般以矩阵乘法为主,也就是涉及到了并行计算。一般来说,单核CPU可以进行的计算种类更多,速度更快,但一般都是单条计算;而显卡能进行的都是基础的并行计算,做矩阵乘法再好不过。如果把所有的矩阵都加载到显卡上,就会导致显卡显存的占用大量增加,尤其是LLM模型大小从7b、14b、34b到几百b不等,占用显存的大小就是惊人的数字,如何在减少运算量和显存占用的条件下,做到推理效果不下降太多呢?在这里需要引入浮点数和定点数的概念。

图片

双精度浮点数: 在PyTorch中用torch.float64表示,或者在其他语言中也称为double类型,在LLM训练中一般比较少用

全精度浮点数: 在PyTorch中用torch.float32表示

低精度浮点数: 在PyTorch中用torch.bfloat16和torch.float16表示。这两个浮点数的差别在上图中可以表示:

  1. bfloat16的小数部分较短,整数部分较长,这会有利于在训练中减少梯度爆炸的情况(即梯度累加值超过了最大值),但是这种数据类型是在N系列显卡Ampere系列才支持的,即30系列显卡。

  2. float16的小数部分较长,这意味着在精度控制上float16更好,但整数部分较短,比较容易梯度爆炸。

那么是否有更加减少显存占用和计算量的数值表达方式呢?那么可以考虑是否把浮点数转换为定点数(整数),整数计算更快更省显存,如果计算精度下降不大就很完美了。这种用整数计算代替浮点数计算的方法就是量化。

量化的基本原理是根据每个tensor的浮点型最大值和最小值,将其映射为一个固定范围的整形数值集合,比如[-127~127]。假设一个简单的公式:qweight=round(weight/scale),其中qweight代表量化后权重,weight代表量化前权重,scale代表缩放因子,可以看到在进行缩放后为了将浮点型转换为整数过程中增加了round操作丢失了小数部分。在后续计算或反量化为浮点型时存在无法完全还原的情况,这就是精度损失。

按照量化发生的步骤区分,可以划分为PTQ(训练后量化,或离线量化)和QAT(训练感知型量化,或在线量化)。PTQ量化可以分为data-free和calibration两种,前者不使用数据集进行校准直接计算量化因子,后者会根据少量真实数据进行统计分析并对量化因子进行额外校准,但耗费的时间更长。QAT量化会先在待量化的算子上增加一个伪量化结构,并在训练时模拟量化过程并实时更新计算量化因子(类似反向传播过程)及原始权重。QAT由于较为复杂一般作为辅助措施存在,用于改进PTQ量化的技术手段。

按照量化方法可以划分为线性量化、非线性量化(如对数量化)等多种方式,目前较为常用的是线性量化。其中线性量化又可以按照对称性划分为对称量化和非对称量化,非对称量化为了解决weight分布不均匀问题,其在公式中增加了zeropoint项:qweight=round(weight/scale + zeropoint),使稠密数据部分可以得到更宽泛的数值范围。

图片

图片

按照量化粒度划分可以分为逐层量化(每层使用一套量化因子)、逐组量化(在每层中按照group使用一套量化因子)、逐通道量化(按channel划分量化因子)等几种方式。

按照量化最大值的阈值区分,可以分为饱和量化和不饱和量化两种。不饱和量化按照浮点数最大值和量化后最大值的比例计算量化因子,由于原始weight的非均匀性会导致某些整形数值范围存在权重空缺。饱和量化会计算一个中间值以计算出量化因子,因此会舍弃一部分不重要数据,将重要数据尽量均匀的分布到量化数值范围内。

按照量化后的比特数划分,可以分为2比特量化,4比特量化,8比特量化等类型。

一般来说,PyTorch中量化模块的forward过程会先对量化权重进行反量化后使用浮点数进行计算。

下面介绍几种常用的量化库。

AutoGPTQ

该库需要引入额外的校准数据集进行量化校准。相比bitsandbytes量化精度较高,推理速度较快,但训练后不支持合并adapter。

# 例子来自于https://github.com/PanQiWei/AutoGPTQ
from modelscope import AutoTokenizer, snapshot_download
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
import logging
import shutil
import oslogging.basicConfig(format="%(asctime)s %(levelname)s [%(name)s] %(message)s", level=logging.INFO, datefmt="%Y-%m-%d %H:%M:%S"
)pretrained_model_dir = snapshot_download("qwen/Qwen-1_8B-Chat")
quantized_model_dir = "qwen-1_8B-4bit"shutil.rmtree(quantized_model_dir, ignore_errors=True)
shutil.copytree(pretrained_model_dir, quantized_model_dir)
for _file in os.listdir(quantized_model_dir):if ".safetensors" in _file or ".bin" in _file:os.remove(os.path.join(quantized_model_dir, _file))tokenizer = AutoTokenizer.from_pretrained(pretrained_model_dir, use_fast=True, trust_remote_code=True)
examples = [tokenizer("auto-gptq is an easy-to-use model quantization library with user-friendly apis, based on GPTQ algorithm.")
]quantize_config = BaseQuantizeConfig(bits=4,  # quantize model to 4-bitgroup_size=128,  # it is recommended to set the value to 128desc_act=False,  # set to False can significantly speed up inference but the perplexity may slightly bad
)# load un-quantized model, by default, the model will always be loaded into CPU memory
model = AutoGPTQForCausalLM.from_pretrained(pretrained_model_dir, quantize_config, trust_remote_code=True).to(0)# quantize model, the examples should be list of dict whose keys can only be "input_ids" and "attention_mask"
model.quantize(examples)# save quantized model
model.save_quantized(quantized_model_dir)# save quantized model using safetensors
model.save_quantized(quantized_model_dir, use_safetensors=True)# load quantized model to the first GPU
model = AutoGPTQForCausalLM.from_quantized(quantized_model_dir, device="cuda:0", trust_remote_code=True)
# inference with model.generate
print(tokenizer.decode(model.generate(**tokenizer("auto_gptq is", return_tensors="pt").to(model.device))[0]))

在SWIFT中,可以使用已经量化好的AutoGPTQ模型直接进行训练:

swift sft --model_id_or_path qwen/Qwen-7B-Chat-Int4 --model_revision master --sft_type lora --tuner_backend swift --template_type qwen --dtype fp16 --output_dir output --dataset leetcode-python-en --train_dataset_sample -1 --num_train_epochs 1 --max_length 512 --check_dataset_strategy warning --lora_rank 8 --lora_alpha 32 --lora_dropout_p 0.05 --lora_target_modules ALL --gradient_checkpointing true --batch_size 1 --weight_decay 0.01 --learning_rate 1e-4

上面的命令行中,qwen/Qwen-7B-Chat-Int4是已经量化好的Qwen-7B-Chat模型。

Bitsandbytes

bitsandbytes是一种data-free的量化库。该量化方法速度较快(因为其不需要数据校准),因此可以在模型加载时动态量化,且该方法训练速度较快,因此训练兼容性较好,一般用于QLoRA训练中,且训练后可以合并adapter。当由于其没有数据校准过程,因此精度较AutoGPTQ较低。

from modelscope import AutoModelForCausalLM, AutoTokenizer
import torchmodel = AutoModelForCausalLM.from_pretrained('qwen/Qwen-1_8B-Chat',load_in_8bit=True,trust_remote_code=True)tokenizer = AutoTokenizer.from_pretrained('qwen/Qwen-1_8B-Chat', trust_remote_code=True)print(model(**tokenizer('how are you?', return_tensors='pt')))

GGML

GGML和GGUF是GGML C++推理库的两种量化格式,其中GGUF格式较新,可以保留模型版本等其他自定义信息。这两种格式也是PTQ形式的量化算法,但GGML和GGUF格式的量化算法更适配于CPU推理,因此在CPU上运行更快,而GPTQ量化对GPU更加友好,两者的推理精度相仿。因此,*.cpp类型使用了GGML推理库的推理框架都更适配于CPU推理。


AWQ

AWQ量化方式假设不是所有权重都影响模型性能,因此在量化过程中会跳过一部分重要权重以减轻量化过程中的精度损失。因此在和GPTQ量化保持类似推理速度的同时可以具备更好的精度。

目前VLLM对AWQ的支持较好, 可以考虑在推理加速时使用AWQ量化方式。

推理部署

推理及部署

训练后的模型会用于推理或者部署。推理即使用模型用输入获得输出的过程,部署是将模型发布到恒定运行的环境中推理的过程。一般来说,LLM的推理可以直接使用PyTorch代码、使用VLLM/XInference/FastChat等框架,也可以使用llama.cpp/chatglm.cpp/qwen.cpp等c++推理框架。

一些推理方法

  • Greedy Search 贪婪搜索方式。按照前面的讲解,模型会按照词表尺寸生成概率。贪婪方式会不断选择生成概率最大的token。该方法由于无脑选择了最大概率,因此模型会倾向于生成重复的文字,一般实际应用中很少使用

  • Beam Search 和贪婪方式的区别在于,beam search会选择概率最大的k个。在生成下一个token时,每个前序token都会生成k个,这样整体序列就有k^2个,从这些序列中选择组合概率最大的k个,并递归地执行下去。k在beam search算法中被称为beam_size

  • Sample 随机采样方式。按照词表每个token的概率采样一个token出来。这个方式多样性更强,是目前主流的生成方式。

重要推理超参数

  • dosample:布尔类型。是否使用随机采样方式运行推理,如果设置为False,则使用beamsearch方式

  • temperature:大于等于零的浮点数。公式为:

,从公式可以看出,如果T取值为0,则效果类似argmax,此时推理几乎没有随机性;取值为正无穷时接近于取平均。一般temperature取值介于[0, 1]之间。取值越高输出效果越随机。如果该问答只存在确定性答案,则T值设置为0。反之设置为大于0。

  • top_k:大于0的正整数。从k个概率最大的结果中进行采样。k越大多样性越强,越小确定性越强。一般设置为20~100之间。

  • 实际实验中可以先从100开始尝试,逐步降低top_k直到效果达到最佳。

  • top_p:大于0的浮点数。使所有被考虑的结果的概率和大于p值,p值越大多样性越强,越小确定性越强。一般设置0.7~0.95之间。

  • 实际实验中可以先从0.95开始降低,直到效果达到最佳。

  • topp比topk更有效,应优先调节这个参数。

  • repetition_penalty: 大于等于1.0的浮点数。如何惩罚重复token,默认1.0代表没有惩罚。

KVCache

上面我们讲过,自回归模型的推理是将新的token不断填入序列生成下一个token的过程。那么,前面token已经生成的中间计算结果是可以直接利用的。具体以Attention结构来说:

图片

推理时的Q是单token tensor,但K和V都是包含了所有历史token tensor的长序列,因此KV是可以使用前序计算的中间结果的,这部分的缓存就是KVCache,其显存占用非常巨大。

VLLM

VLLM支持绝大多数LLM模型的推理加速。它使用如下的方案大幅提升推理速度:

  1. Continuous batching
  • 在实际推理过程中,一个批次多个句子的输入的token长度可能相差很大,最后生成的模型输出token长度相差也很大。在python朴素推理中,最短的序列会等待最长序列生成完成后一并返回,这意味着本来可以处理更多token的GPU算力在对齐过程中产生了浪费。continous batching的方式就是在每个句子序列输出结束后马上填充下一个句子的token,做到高效利用算力。

图片

图片

2. PagedAttention

  • 推理时的显存占用中,KVCache的碎片化和重复记录浪费了50%以上的显存。VLLM将现有输入token进行物理分块,使每块显存内部包含了固定长度的tokens。在进行Attention操作时,VLLM会从物理块中取出KVCache并计算。因此模型看到的逻辑块是连续的,但是物理块的地址可能并不连续。这和虚拟内存的思想非常相似。另外对于同一个句子生成多个回答的情况,VLLM会将不同的逻辑块映射为一个物理块,起到节省显存提高吞吐的作用。

图片

图片

值得注意的是,VLLM会默认将显卡的全部显存预先申请以提高缓存大小和推理速度,用户可以通过参数gpu_memory_utilization控制缓存大小。

首先安装VLLM:

pip install vllm
import os
os.environ['VLLM_USE_MODELSCOPE'] = 'True'
from vllm import LLM, SamplingParams
prompts = ["Hello, my name is","The president of the United States is","The capital of France is","The future of AI is",
]
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
llm = LLM(model="qwen/Qwen-1_8B", trust_remote_code=True)
outputs = llm.generate(prompts, sampling_params)# Print the outputs.
for output in outputs:prompt = output.promptgenerated_text = output.outputs[0].textprint(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

注意,截止到本文档编写完成,VLLM对Chat模型的推理支持(模板和结束符)存在问题,在实际进行部署时请考虑使用SWIFT或者FastChat。

LLM的generate方法支持直接输入拼接好的tokens(prompttokenids参数,此时不要传入prompts参数),所以外部可以按照自己的模板进行拼接后传入VLLM,

在前文量化章节中我们讲解了AWQ量化,VLLM直接支持传入量化后的模型进行推理:

from vllm import LLM, SamplingParams
import os
import torch
os.environ['VLLM_USE_MODELSCOPE'] = 'True'# Sample prompts.
prompts = ["Hello, my name is","The president of the United States is","The capital of France is","The future of AI is",
]
# Create a sampling params object.
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)# Create an LLM.
llm = LLM(model="ticoAg/Qwen-1_8B-Chat-Int4-awq", quantization="AWQ", dtype=torch.float16, trust_remote_code=True)
# Generate texts from the prompts. The output is a list of RequestOutput objects
# that contain the prompt, generated text, and other information.
outputs = llm.generate(prompts, sampling_params)
# Print the outputs.
for output in outputs:prompt = output.promptgenerated_text = output.outputs[0].textprint(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

VLLM官方文档:https://docs.vllm.ai/en/latest/getting_started/quickstart.html

SWIFT

在SWIFT中,我们支持了VLLM的推理加速手段。

pip install ms-swift[llm] openai

只需要运行下面的命令就可以使用VLLM加速推理:

swift infer --model_id_or_path qwen/Qwen-1_8B-Chat --max_new_tokens 128 --temperature 0.3 --top_p 0.7 --repetition_penalty 1.05 --do_sample true

也支持在部署中使用VLLM:

swift deploy --model_id_or_path qwen/Qwen-1_8B-Chat --max_new_tokens 128 --temperature 0.3 --top_p 0.7 --repetition_penalty 1.05 --do_sample true

调用:

from openai import OpenAI
client = OpenAI(api_key='EMPTY',base_url='http://localhost:8000/v1',
)
model_type = client.models.list().data[0].id
print(f'model_type: {model_type}')query = '浙江的省会在哪里?'
messages = [{'role': 'user','content': query
}]
resp = client.chat.completions.create(model=model_type,messages=messages,seed=42)
response = resp.choices[0].message.content
print(f'query: {query}')
print(f'response: {response}')# 流式
messages.append({'role': 'assistant', 'content': response})
query = '这有什么好吃的?'
messages.append({'role': 'user', 'content': query})
stream_resp = client.chat.completions.create(model=model_type,messages=messages,stream=True,seed=42)print(f'query: {query}')
print('response: ', end='')
for chunk in stream_resp:print(chunk.choices[0].delta.content, end='', flush=True)
print()"""Out[0]
model_type: qwen-7b-chat
query: 浙江的省会在哪里?
response: 浙江省的省会是杭州市。
query: 这有什么好吃的?
response: 杭州有许多美食,例如西湖醋鱼、东坡肉、龙井虾仁、叫化童子鸡等。此外,杭州还有许多特色小吃,如西湖藕粉、杭州小笼包、杭州油条等。
"""

llama.cpp

llama.cpp是使用c++语言编写的对llama系列模型进行高效推理或量化推理的开源库。该库使用了ggml底层计算库进行推理。在使用之前需要额外将python的weights转为ggml格式或gguf格式方可使用。和llama.cpp类似,还有兼容ChatGLM模型的chatglm.cpp和兼容qwen模型的qwen.cpp和mistral的mistral.cpp。

安装依赖:

pip install modelscope
git clone --recursive https://github.com/QwenLM/qwen.cpp && cd qwen.cpp
cmake -B build
cmake --build build -j --config Release

下载模型:

from modelscope import snapshot_download
print(snapshot_download('qwen/Qwen-1_8B-Chat'))
# /mnt/workspace/.cache/modelscope/qwen/Qwen-1_8B-Chat

将原始模型转换为ggml支持的格式:

python3 qwen_cpp/convert.py -i /mnt/workspace/.cache/modelscope/qwen/Qwen-1_8B-Chat -t q4_0 -o qwen1_8b-ggml.bin
./build/bin/main -m qwen1_8b-ggml.bin --tiktoken /mnt/workspace/.cache/modelscope/qwen/Qwen-1_8B-Chat/qwen.tiktoken -p 你好
# 你好!有什么我可以帮助你的吗?

量化章节中我们介绍,GGML库适合于CPU运行,因此推荐用户在CPU环境中或边缘计算中考虑cpp库进行推理。

FastChat

FastChat是一个开源推理库,侧重于模型的分布式部署实现,并提供了OpenAI样式的RESTFul API。

pip3 install "fschat[model_worker,webui]"
python3 -m fastchat.serve.controller

在新的terminal中启动:

FASTCHAT_USE_MODELSCOPE=true python3 -m fastchat.serve.model_worker --model-path qwen/Qwen-1_8B-Chat --revision v1.0.0

之后在新的terminal中可以运行界面进行推理:

python3 -m fastchat.serve.gradio_web_server

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/686255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构实验之栈与队列七:出栈序列判定

数据结构实验之栈与队列七:出栈序列判定 Description 给一个初始的入栈序列,其次序即为元素的入栈次序,栈顶元素可以随时出栈,每个元素只能入栈依次。输入一个入栈序列,后面依次输入多个序列,请判断这些序…

【web | CTF】BUUCTF [BJDCTF2020]Easy MD5

天命:好像也挺实用的题目,也是比较经典吧 天命:把php的MD5漏洞都玩了一遍 第一关:MD5绕过 先声明一下:这题的MD5是php,不是mysql的MD5,把我搞迷糊了 一进来题目啥也没有,那么就要看…

物理机安装kali

ventoyU盘,ventoy做好后把kali的iso拷贝到U盘,设置U盘启动,选择kali.iso启动。 安装包 文件SHA256发布日期大小ventoy-1.0.97-windows.zip44fb53f26872c6304e1cb3d47b65d0613665666100c48deeee4cd87901fb500f2024-01-2415 MBventoy-1.0.97-linux.tar.g…

Python OpenCV 牛刀小试(练习)

BGR与RGB OpenCV在读取图像时,默认的颜色空间是BGR(蓝绿红),而在大多数其他的图像处理库和图像格式中,使用的颜色空间是RGB(红绿蓝)。因此,当你需要使用OpenCV处理图像,然…

python系统学习Day3

section4 python function part one:函数的参数 python函数的参数共有五种类型 #位置参数 def power(x):return x * x#默认参数 def power(x, n 2) #设置默认值(可省略)s 1while n > 0:n n - 1s s * xreturn s#note print(默认参数必…

人工智能学习与实训笔记(十五):Scikit-learn库的基础与使用

人工智能专栏文章汇总:人工智能学习专栏文章汇总-CSDN博客 本篇目录 一、介绍 1. 1 Scikit-learn的发展历程及定义 1.2 理解算法包、算法库及算法框架之间的区别和联系 二、Scikit-learn官网结构 三、安装与设置 3.1 Python环境的安装与配置 3.2 Scikit-lea…

【leetcode刷题之路】面试经典150题(1)——数组/字符串

文章目录 1 数组/字符串1.1 【排序】合并两个有序数组1.2【双指针】移除元素1.3 【双指针】删除有序数组中的重复项1.4 【双指针】删除有序数组中的重复项 II1.5 【数学】多数元素1.6 【数组】轮转数组1.7 【动态规划】买卖股票的最佳时机1.8 【贪心】买卖股票的最佳时机 II1.9…

【Windows】MacOS制作纯净版Windows10安装U盘

方法一、在window系统中更新win10(不更新引导程序) cp -rp /Volumes/Windows10专业版\ 64位/* /Volumes/WIN10/https://baijiahao.baidu.com/s?id1760695844372493842&wfrspider&forpc 方法二、在window系统中更新win10(更新引导程…

《Docker极简教程》--Docker容器--Docker容器的创建和使用

一、创建Docker容器 1.1 使用现有镜像创建容器 当使用现有镜像创建容器时,通常会涉及以下步骤: 获取镜像:首先,需要从Docker Hub或其他镜像仓库获取所需的镜像。可以使用docker pull命令来获取镜像,语法如下&#x…

45. 跳跃游戏 II(难度:中等)

题目链接:https://leetcode.cn/problems/jump-game-ii/ 题目描述: 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳…

软件实例分享,洗车店系统管理软件会员卡电子系统教程

软件实例分享,洗车店系统管理软件会员卡电子系统教程 一、前言 以下软件教程以 佳易王洗车店会员管理软件V16.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、会员卡号可以绑定车牌号或手机号 2、卡号也可以直接使用手机号&a…

【Java万花筒】优雅配置,从容应对:Java配置管理库深度解读

灵活应对变化:Java配置管理库全景解析 前言 在构建现代化的Java应用时,配置管理是一个至关重要的方面。精心设计的配置管理能够为应用提供灵活性、可维护性和适应性,而Java社区提供了多种优秀的配置管理库。本文将深入探讨一些主流的Java配…

优秀的电机驱动MCU:MM32SPIN360C

DC-DC电源布局注意点: 电源模块布局布线可提前下载芯片的datasheet(数据表),按照推荐的布局和布线进行设计。 1) 芯片电源接近原则: 对于为芯片提供电压的开关电源,应确保它尽量靠近芯片放置。这样可以避…

2024 CKS 题库 | 8、沙箱运行容器 gVisor

不等更新题库 CKS 题库 8、沙箱运行容器 gVisor Context 该 cluster 使用 containerd 作为 CRI 运行时。containerd 的默认运行时处理程序是 runc 。 containerd 已准备好支持额外的运行时处理程序 runsc (gVisor)。 Task 使用名为 runsc 的现有运行时处理程序,…

【打工日常】使用docker部署可视化工具docker-ui

一、docker-ui介绍 docker-ui是一个易用且轻量化的Docker管理工具,透过Web界面的操作,方便快捷操作docker容器化工作。 docker-ui拥有易操作化化界面,不须记忆docker指令,仅需下载镜像即可立刻加入完成部署。基于docker的特性&…

幻兽帕鲁新手游戏攻略分享

在幻兽帕鲁中,提高实力是玩家不断追求的目标。以下是一些提高实力的攻略: 1、升级和进化:通过战斗和完成任务,玩家可以获得经验值,提升自己的等级。随着等级的提升,玩家可以获得技能点,用于提升…

AGAST角点检测

一、AGAST角点检测 C #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/common/io.h> #include <pcl/visualization/pcl_visualizer.h> #include <boost/thread/thread.hpp> #include <p…

支付交易——跨境交易

摘要 老王兢兢业业经营生意多年&#xff0c;一步步从小杂货店做到现在&#xff0c;成立大型贸易公司。在做大做强的过程中&#xff0c;老王觉得国内市场已经饱和&#xff0c;竞争处处是红海。老王留意海外很多年了&#xff0c;决定走出去&#xff0c;转向海外:将国外的商品引进…

【51单片机】AD模数转换DA数模转换(江科大)

1.AD/DA介绍 AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号 DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号 AD/DA转换打开了计算机与模拟信号的大门,极大的提高了计算机系统的应用范围,也为模拟信号数字化处理…

RestTemplate自定义设置

增加类&#xff1a;RestTemplateConfig import org.apache.http.client.HttpClient; import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.Htt…