【LLM】deepseek R1之GRPO训练笔记(持续更新)

note

  • 相关框架对比:
    • 需微调模型且资源有限 → Unsloth;
    • 本地隐私优先的小规模推理 → Ollama;
    • 复杂逻辑或多模态任务 → SGLang;
    • 高并发生产环境 → vLLM
  • 微调SFT和GRPO是确实能学到新知识的
  • 四种格式(messagessharegptalpacaquery-response)在AutoPreprocessor处理下都会转换成ms-swift标准格式中的messages字段,即都可以直接使用--dataset <dataset-path>接入,即可直接使用json数据

文章目录

  • note
  • 一、Swift框架
    • 数据集定义
    • 奖励函数
    • GRPO公式
    • 训练参数
    • 训练结果
  • 二、unsloth框架
    • 1. Unsloth框架介绍
    • 2. 使用
    • 3. 训练参数
  • 三、open r1项目
    • 数据生成
    • 模型训练
    • 模型评估
  • 四、GRPO经验总结
    • 关于DeepseekR1的17个观点
  • Reference

一、Swift框架

数据集定义

Coundown Game任务:给定几个数字,进行加减乘除后得到目标数值。
数据量:5w条

[INFO:swift] train_dataset: Dataset({features: ['nums', 'messages', 'target'],num_rows: 49500
})
[INFO:swift] val_dataset: Dataset({features: ['nums', 'messages', 'target'],num_rows: 500
})

通过 template, 使用 numbers 和 target 完成任务定义,并给到 query 字段供模型采样使用。同时,我们需要保留 nums 和 target 两个字段,用于后续的奖励函数计算。

class CoundownTaskPreprocessor(ResponsePreprocessor):def preprocess(self, row: Dict[str, Any]) -> Dict[str, Any]:numbers = row['nums']target = row.pop('response', None)query = f"""Using the numbers {numbers}, create an equation that equals {target}.You can use basic arithmetic operations (+, -, *, /) and each number can only be used once.Show your work in <think> </think> tags. And return the final equation and answer in <answer> </answer> tags,for example <answer> (1 + 2) / 3 * 4 = 4 </answer>."""row.update({'target': target, 'query': query})return super().preprocess(row)register_dataset(DatasetMeta(ms_dataset_id='zouxuhong/Countdown-Tasks-3to4',subsets=['default'],preprocess_func=CoundownTaskPreprocessor(),tags=['math']))

奖励函数

  • 格式奖励函数:Deepseek-R1 中提到的格式奖励函数,已经在swift中内置,通过 --reward_funcs format 可以直接使用
  • 准确性奖励函数:使用 external_plugin 的方式定义准确性奖励函数,将代码放在swift/examples/train/grpo/plugin/plugin.py中。
    • 奖励函数的输入包括 completions、target 和 nums 三个字段,分别表示模型生成的文本、目标答案和可用的数字。
    • 每个都是list,支持多个 completion 同时计算。注意这里除了 completions 之外的参数都是数据集中定义的字段透传而来,如果有任务上的变动,可以分别对数据集和奖励函数做对应的改变即可。
class CountdownORM(ORM):def __call__(self, completions, target, nums, **kwargs) -> List[float]:"""Evaluates completions based on Mathematical correctness of the answerArgs:completions (list[str]): Generated outputstarget (list[str]): Expected answersnums (list[str]): Available numbersReturns:list[float]: Reward scores"""rewards = []for completion, gt, numbers in zip(completions, target, nums):try:# Check if the format is correctmatch = re.search(r"<answer>(.*?)<\/answer>", completion)if match is None:rewards.append(0.0)continue# Extract the "answer" part from the completionequation = match.group(1).strip()if '=' in equation:equation = equation.split('=')[0]# Extract all numbers from the equationused_numbers = [int(n) for n in re.findall(r'\d+', equation)]# Check if all numbers are used exactly onceif sorted(used_numbers) != sorted(numbers):rewards.append(0.0)continue# Define a regex pattern that only allows numbers, operators, parentheses, and whitespaceallowed_pattern = r'^[\d+\-*/().\s]+$'if not re.match(allowed_pattern, equation):rewards.append(0.0)continue# Evaluate the equation with restricted globals and localsresult = eval(equation, {"__builti'ns__": None}, {})# Check if the equation is correct and matches the ground truthif abs(float(result) - float(gt)) < 1e-5:rewards.append(1.0)else:rewards.append(0.0)except Exception as e:# If evaluation fails, reward is 0rewards.append(0.0)return rewards
orms['external_countdown'] = CountdownORM

GRPO公式

J G R P O ( θ ) = E [ q ∼ P ( Q ) , { o i } i = 1 G ∼ π θ o l d ( O ∣ q ) ] 1 G ∑ i = 1 G 1 ∣ o i ∣ ∑ t = 1 ∣ o i ∣ { min ⁡ [ π θ ( o i , t ∣ q , o i , < t ) π θ o l d ( o i , t ∣ q , o i , < t ) A ^ i , t , clip ⁡ ( π θ ( o i , t ∣ q , o i , < t ) π θ o l d ( o i , t ∣ q , o i , < t ) , 1 − ε , 1 + ε ) A ^ i , t ] − β D K L [ π θ ∣ ∣ π r e f ] } \begin{aligned} \mathcal{J}_{G R P O}(\theta) & =\mathbb{E}\left[q \sim P(Q),\left\{o_i\right\}_{i=1}^G \sim \pi_{\theta_{o l d}}(O \mid q)\right] \\ & \frac{1}{G} \sum_{i=1}^G \frac{1}{\left|o_i\right|} \sum_{t=1}^{\left|o_i\right|}\left\{\min \left[\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{o l d}}\left(o_{i, t} \mid q, o_{i,<t}\right)} \hat{A}_{i, t}, \operatorname{clip}\left(\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{o l d}}\left(o_{i, t} \mid q, o_{i,<t}\right)}, 1-\varepsilon, 1+\varepsilon\right) \hat{A}_{i, t}\right]-\beta \mathbb{D}_{K L}\left[\pi_\theta| | \pi_{r e f}\right]\right\} \end{aligned} JGRPO(θ)=E[qP(Q),{oi}i=1Gπθold(Oq)]G1i=1Goi1t=1oi{min[πθold(oi,tq,oi,<t)πθ(oi,tq,oi,<t)A^i,t,clip(πθold(oi,tq,oi,<t)πθ(oi,tq,oi,<t),1ε,1+ε)A^i,t]βDKL[πθ∣∣πref]}

训练参数

选取 Qwen2.5-3B-Instruct 作为基础模型进行训练,选取 Instruct 而不是基模的主要原因是可以更快地获取 format reward。我们在三卡 GPU 上进行实验,因此vllm的推理部署在最后一张卡上,而进程数设置为2,在剩下两张卡上进行梯度更新。

由于任务较为简单,我们设置 max_completion_lengthvllm_max_model_len 为1024,如果有更复杂的任务,可以适当加大模型输出长度。注意,这两个参数越大,模型训练需要的显存越多,训练速度越慢,单个step的训练时间与max_completion_length呈现线性关系

在我们的实验中,总batch_size为 n u m _ p r o c e s s e s × p e r _ d e v i c e _ t r a i n _ b a t c h _ s i z e × g r a d i e n t _ a c c u m u l a t i o n _ s t e p s = 2 × 8 × 8 = 128 num\_processes \times per\_device\_train\_batch\_size \times gradient\_accumulation\_steps = 2 \times 8 \times 8 = 128 num_processes×per_device_train_batch_size×gradient_accumulation_steps=2×8×8=128 而参数设置有一个限制,即: n u m _ p r o c e s s e s × p e r _ d e v i c e _ t r a i n _ b a t c h _ s i z e num\_processes \times per\_device\_train\_batch\_size num_processes×per_device_train_batch_size 必须整除 n u m _ g e n e r a t i o n s num\_generations num_generations,其中, n u m _ g e n e r a t i o n s num\_generations num_generations就是GRPO公式中的 G G G,故我们设置为8。

注意:

  • 这里单卡batch_size设置也与显存息息相关,请根据显存上限设置一个合适的值。
  • 总的steps数量 : n u m _ s t e p s = e p o c h s × l e n ( d a t a s e t s ) × n u m _ g e n e r a t i o n s ÷ b a t c h _ s i z e num\_steps = epochs \times len(datasets) \times num\_generations \div batch\_size num_steps=epochs×len(datasets)×num_generations÷batch_size,需要根据这个来合理规划训练的学习率和warmup设置。
  • 设置是学习率和 beta,学习率比较好理解,而beta则是是以上公式的 β \beta β,即KL散度的梯度的权重。这两个参数设置的越大,模型收敛原则上更快,但训练往往会不稳定。经过实验,我们分别设置为 5e-70.001。在实际训练中,请根据是否出现不稳定的震荡情况适当调整这两个参数。
  • 对于KL散度,社区有很多的讨论,可以参考为什么GRPO坚持用KL散度。
  • 具体的参数介绍:https://swift.readthedocs.io/zh-cn/latest/Instruction/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0.html
CUDA_VISIBLE_DEVICES=0,1,2 \
WANDB_API_KEY=your_wandb_key \
NPROC_PER_NODE=2 \
swift rlhf \--rlhf_type grpo \--model Qwen/Qwen2.5-3B-Instruct \--external_plugins examples/train/grpo/plugin/plugin.py \--reward_funcs external_countdown format \--use_vllm true \--vllm_device auto \--vllm_gpu_memory_utilization 0.6 \--train_type full \--torch_dtype bfloat16 \--dataset 'zouxuhong/Countdown-Tasks-3to4#50000' \--max_length 2048 \--max_completion_length 1024 \--num_train_epochs 1 \--per_device_train_batch_size 8 \--per_device_eval_batch_size 8 \--learning_rate 5e-7 \--gradient_accumulation_steps 8 \--eval_steps 500 \--save_steps 100 \--save_total_limit 20 \--logging_steps 1 \--output_dir output/GRPO_COUNTDOWN \--warmup_ratio 0.01 \--dataloader_num_workers 4 \--num_generations 8 \--temperature 1.0 \--system 'You are a helpful assistant. You first thinks about the reasoning process in the mind and then provides the user with the answer.' \--deepspeed zero3 \--log_completions true \--vllm_max_model_len 1024 \--report_to wandb \--beta 0.001 \--num_iterations 1

训练结果

(1)reward_std开始还波动着,300step后降到0左右,说明最后训练也较为收敛了:
在这里插入图片描述

二、unsloth框架

链接:https://docs.unsloth.ai/basics/reasoning-grpo-and-rl/tutorial-train-your-own-reasoning-model-with-grpo

1. Unsloth框架介绍

  1. 开源项目Unsloth AI实现重大突破,通过优化GRPO训练方法,将内存使用减少80%,让7GB显存GPU就能本地运行DeepSeek-R1级别的推理模型;
  2. Unsloth实现了与vLLM的深度整合,可将模型吞吐量提升20倍,同时仅需一半VRAM,使单张48GB GPU就能微调Llama 3.3 70B;
  3. 该项目在GitHub获2万多星,其核心团队仅由两兄弟组成,成功大幅降低了AI推理模型的部署门槛。本地也能体验「Aha」 时刻:现在可以在本地设备上复现DeepSeek-R1的推理!只需7GB VRAM,你就能体验到「Aha」时刻。Unsloth把GRPO训练需要的内存减少了80%。15GB VRAM就可以把Llama-3.1(8B)和Phi-4(14B)转变为推理模型。

2. 使用

unsloth是推理、微调一体式框架,unsloth将Llama 3.3、Mistral、Phi-4、Qwen 2.5和Gemma的微调速度提高2倍,同时节省80%的内存。官网地址:GitHub - unslothai/unsloth: Finetune Llama 3, Mistral & Gemma LLMs 2-5x faster with 80% less memoryhttps://github.com/unslothai/unsloth

使用如下命令快速安装:

pip install unslothpip install --force-reinstall --no-cache-dir --no-deps git+https://github.com/unslothai/unsloth.git

3. 训练参数

SFTTTrainer 进行监督微调(Supervised Fine-Tuning, SFT),适用于 transformers 和 Unsloth 生态中的模型微调:1. 相关库

  • SFTTrainer(来自 trl 库):

    • trl(Transformer Reinforcement Learning)是 Hugging Face 旗下的 trl 库,提供监督微调(SFT)和强化学习(RLHF)相关的功能。
    • SFTTrainer 主要用于有监督微调(Supervised Fine-Tuning),适用于 LoRA 等低秩适配微调方式。
  • TrainingArguments(来自 transformers 库):

    • 这个类用于定义训练超参数,比如批量大小、学习率、优化器、训练步数等。
  • is_bfloat16_supported(来自 unsloth):

    • 这个函数检查当前 GPU 是否支持 bfloat16(BF16),如果支持,则返回 True,否则返回 False
    • bfloat16 是一种更高效的数值格式,在新款 NVIDIA A100/H100 等GPU上表现更优。

SFTTrainer 部分
在这里插入图片描述

TrainingArguments 部分
在这里插入图片描述

参考:从零开始的DeepSeek微调训练实战(SFT)阿里云开发社区

三、open r1项目

一个parquet文件:/root/paddlejob/workspace/env_run/gtest/rl_train/data/OpenR1-Math-220k/open-r1/OpenR1-Math-220k/all/train-00001-of-00020.parquet

SFT训练:

# Train via command line
accelerate launch --config_file=recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \--model_name_or_path Qwen/Qwen2.5-1.5B-Instruct \--dataset_name open-r1/OpenR1-Math-220k \--learning_rate 1.0e-5 \--num_train_epochs 1 \--packing \--max_seq_length 16384 \--per_device_train_batch_size 16 \--gradient_checkpointing \--bf16 \--output_dir data/Qwen2.5-1.5B-Open-R1-Distill# Train via YAML config
accelerate launch --config_file recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \--config recipes/Qwen2.5-1.5B-Instruct/sft/config_demo.yaml

GRPO训练:

ACCELERATE_LOG_LEVEL=info accelerate launch --config_file recipes/accelerate_configs/zero2.yaml \--num_processes=7 src/open_r1/grpo.py \--config recipes/DeepSeek-R1-Distill-Qwen-1.5B/grpo/config_demo.yaml

数据生成

数据生成:为了构建 OpenR1-220k,我们使用 DeepSeek R1 大语言模型生成 NuminaMath 1.5 中 40 万个问题的解决方案。我们遵循模型卡的推荐参数,并在用户提示词前添加以下指令:“请逐步推理,并将最终答案放在 \boxed{} 中。”

from datasets import load_dataset
from distilabel.models import vLLM
from distilabel.pipeline import Pipeline
from distilabel.steps.tasks import TextGenerationprompt_template = """\
You will be given a problem. Please reason step by step, and put your final answer within \boxed{}:
{{ instruction }}"""dataset = load_dataset("AI-MO/NuminaMath-TIR", split="train").select(range(10))model_id = "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B"  # Exchange with another smol distilled r1with Pipeline(name="distill-qwen-7b-r1",description="A pipeline to generate data from a distilled r1 model",
) as pipeline:llm = vLLM(model=model_id,tokenizer=model_id,extra_kwargs={"tensor_parallel_size": 1,"max_model_len": 8192,},generation_kwargs={"temperature": 0.6,"max_new_tokens": 8192,},)prompt_column = "problem"text_generation = TextGeneration(llm=llm, template=prompt_template,num_generations=4,input_mappings={"instruction": prompt_column} if prompt_column is not None else {})if __name__ == "__main__":distiset = pipeline.run(dataset=dataset)distiset.push_to_hub(repo_id="username/numina-deepseek-r1-qwen-7b")

提示词:

You are a mathematical answer validator. You will be provided with a mathematical problem and you need to compare the answer in the reference solution, and the final answer in a model's solution to determine if they are equivalent, even if formatted differently.PROBLEM:{problem}REFERENCE SOLUTION:{answer}MODEL'S SOLUTION:{generation}Focus ONLY on comparing the final mathematical answer provided by the model while ignoring differences in:- Formatting (e.g., \\boxed{{}} vs plain text)
- Multiple choice formatting (e.g., "A" vs full solution)
- Order of coordinate pairs or solutions
- Equivalent mathematical expressions or notation variations
- If the model's answer is nonsense, return "Verdict: AMBIGUOUS"Start with a brief explanation of your comparison (2-3 sentences). Then output your final answer in one of the following formats:- "Verdict: EQUIVALENT"
- "Verdict: DIFFERENT"
- "Verdict: AMBIGUOUS"

模型训练

模型评估

在几个经典benchmark上评估:

MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
MODEL_ARGS="pretrained=$MODEL,dtype=bfloat16,max_model_length=32768,gpu_memory_utilization=0.8,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
OUTPUT_DIR=data/evals/$MODEL# AIME 2024
TASK=aime24
lighteval vllm $MODEL_ARGS "custom|$TASK|0|0" \--custom-tasks src/open_r1/evaluate.py \--use-chat-template \--output-dir $OUTPUT_DIR# MATH-500
TASK=math_500
lighteval vllm $MODEL_ARGS "custom|$TASK|0|0" \--custom-tasks src/open_r1/evaluate.py \--use-chat-template \--output-dir $OUTPUT_DIR# GPQA Diamond
TASK=gpqa:diamond
lighteval vllm $MODEL_ARGS "custom|$TASK|0|0" \--custom-tasks src/open_r1/evaluate.py \--use-chat-template \--output-dir $OUTPUT_DIR# LiveCodeBench
lighteval vllm $MODEL_ARGS "extended|lcb:codegeneration|0|0" \--use-chat-template \--output-dir $OUTPUT_DIR 

四、GRPO经验总结

关于DeepseekR1的17个观点

DeepseekR1总结,在 DeepSeek-R1 发布 100 天后,我们学到了什么?,100 Days After DeepSeek-R1: A Survey on Replication Studies and More Directions for Reasoning Language Models,https://arxiv.org/pdf/2505.00551,DeepSeek-R1模型发布后的100天内,学术界对其复制研究的进展和未来发展方向。

17个观点:
1、高质量、经过验证的思维链(Chain-of-Thought, CoT)数据对于监督微调(Supervised Fine-Tuning, SFT)是有效的。
2、为 SFT 挑选更难的问题(例如,基于较弱模型的低通过率筛选)能显著提升模型性能。
3、开放数据集中混杂有基准测试样本,需要仔细进行数据去污染(decontamination)以保证公平评估。
4、倾向于包含更长 CoT(通常意味着问题更复杂)的数据集,在 SFT 后往往能带来更好的推理性能。
5、SFT 能有效地赋予模型推理结构,为后续的强化学习(Reinforcement Learning, RL)奠定必要基础。
6、相较于基础模型,已经过指令微调的模型在 SFT 阶段能更有效地学习推理模式。
7、强化学习(RL)数据集受益于严格的验证过程(例如使用数学求解器、代码执行)以及筛选掉模型可能出错的“不确定性”样本。
8、使用简单的、可验证的、基于结果的奖励(例如,判断对错)是有效的,并且能降低奖励操纵(reward hacking)的风险。
9、在推理模型的强化学习(RL for Verification/Reasoning)中,明确的格式或长度奖励的必要性和益处尚存争议,有时模型可以隐式地学习这些方面。
10、PPO 和 GRPO 是最常用的 RL 算法,但它们的变体(如 DAPO、Dr. GRPO、VC-PPO、VAPO)被设计用于解决偏差(如长度偏差、难度偏差)和训练不稳定性问题。
11、KL 损失虽然常用于提升训练稳定性,但在推理模型的 RL 训练中有时会被省略,或者发现它会限制模型的探索能力和最终的性能提升。
12、在 RL 训练过程中,逐步增加训练样本的难度或模型允许的最大响应长度,有助于提升性能和稳定性。
13、将训练重点放在更难的样本上,或者剔除模型已经“学会解决”的简单样本,这类策略可以提升 RL 的训练效率。
14、集成了价值函数的方法(如 VC-PPO、VAPO)在处理长 CoT 问题时,其表现可能优于无价值函数的方法(如 GRPO)。
15、RL 训练能够提升模型的域外泛化能力,其效果可能超越单独使用 SFT,甚至能泛化到看似不相关的任务上(例如,通过数学/代码训练提升写诗能力)。
16、推理模型带来了新的安全挑战,例如奖励操纵(reward hacking)、过度思考(overthinking)以及特定的越狱(jailbreaking)漏洞。
17、对于较小规模的模型(例如 <32B 参数),相比于使用蒸馏得到的检查点(distilled checkpoints),单纯依靠 RL 来复现最佳性能通常更具挑战性。

Reference

[1] Open R1 项目 第二周总结与展望
[2] 摸着Logic-RL,复现7B - R1 zero
[3] https://huggingface.co/blog/open-r1/update-2
[4] 用极小模型复现R1思维链的失败感悟
[5] https://github.com/Unakar/Logic-RL
[6] 【LLM-RL】强化对齐之GRPO算法和微调实践
[7] 官方文档:https://docs.unsloth.ai/get-started/fine-tuning-guide
[8] https://huggingface.co/datasets/yahma/alpaca-cleaned/viewer
[9] 官方文档跑GRPO:https://docs.unsloth.ai/basics/reasoning-grpo-and-rl/tutorial-train-your-own-reasoning-model-with-grpo
[10] R1复现小记:在业务场景的两类NLP任务上有显著效果 NLP工作站
[11] 批判性视角看待 R1 训练(基础模型和强化学习)中的坑
[12] MLNLP社区发布《动画中学强化学习笔记》项目!
[13] 【LLM】R1复现项目(SimpleRL、OpenR1、LogitRL、TinyZero)持续更新
[14] 项目地址:https://github.com/MLNLP-World/Reinforcement-Learning-Comic-Notes
[15] 笔记:https://github.com/MLNLP-World/Reinforcement-Learning-Comic-Notes/tree/main/note
[16] unsloth官方微调指南:https://docs.unsloth.ai/get-started/fine-tuning-guide
[17] unsloth官方GRPO指南:https://docs.unsloth.ai/basics/reasoning-grpo-and-rl
[18] 基于unsloth框架完成7B规模模型SFT微调训练(10GB显存占用) bookname,某乎
[19] 使用Unsloth训练自己的R1模型.中科院计算所
[20] GRPO中的KL Loss实现细节问题
[21] 个性训练(2)-借助GRPO提升多轮对话能力
[22] 个性训练-借助GRPO塑造一个有个性且智商在线的大模型
[23] 为什么大家都在吹deepseek的GRPO?某乎
[24] Datasets Guide 数据集指南
[25] 基于qwen2.5进行GRPO训练:https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2.5_(3B)-GRPO.ipynb
[26] DeepSeek同款GRPO训练大提速!魔搭开源全流程方案,支持多模态训练、训练加速和评测全链路
[27] 聊聊DeepSeek-R1-Distilled-QWen32B基于GRPO算法下的训练记录——基于ms-swift训推框架
[28] ​多模态GRPO完整实验流程- swift 小健
[29] swift官方文档GRPO训练过程:https://swift.readthedocs.io/zh-cn/latest/BestPractices/GRPO%E5%AE%8C%E6%95%B4%E6%B5%81%E7%A8%8B.html
[30] [Wandb] api key怎么查看
[31] 多模态GRPO完整实验流程.swift官方文档
[32] AI大模型ms-swift框架实战指南(十):自定义数据集微调实践大全
[33] 大模型团队搞GRPO强化学习,一些小Tips2

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

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

相关文章

【数据结构】--- 单链表的增删查改

前言&#xff1a; 经过了几个月的漫长岁月&#xff0c;回头时年迈的小编发现&#xff0c;数据结构的内容还没有写博客&#xff0c;于是小编赶紧停下手头的活动&#xff0c;补上博客以洗清身上的罪孽 目录 前言 概念&#xff1a; 单链表的结构 我们设定一个哨兵位头节点给链…

【JAVA】数据类型与变量:深入理解栈内存分配(4)

核心知识点详细解释 Java 的基本数据类型和引用数据类型 基本数据类型 Java 有 8 种基本数据类型&#xff0c;它们可以分为 4 类&#xff1a; 整数类型&#xff1a;byte&#xff08;1 字节&#xff09;、short&#xff08;2 字节&#xff09;、int&#xff08;4 字节&#…

ReentrantLock实现公平锁和非公平锁

在 Java 里&#xff0c;公平锁和非公平锁是多线程编程中用于同步的两种锁机制&#xff0c;它们的主要差异在于获取锁的顺序规则。下面是对二者的详细介绍&#xff1a; 公平锁 公平锁遵循 “先来先服务” 原则&#xff0c;也就是线程获取锁的顺序和请求锁的顺序一致。先请求锁…

一篇撸清 Http,SSE 与 WebSocket

HTTP,SSE 和WebSocket都是网络传输的协议,本篇快速介绍三者的概念和比较。 SSE(Server-Sent Events) 是什么? SSE(Server-Sent Events),服务器发送事件, 是一种基于 HTTP 的轻量级协议,允许服务器主动向客户端(如浏览器)推送实时数据。它设计用于单向通信(服务器到…

5个重要的财务指标讲解

1&#xff09;净资产收益率 2&#xff09;销售净利率 3&#xff09; 销售毛利率 4&#xff09;销售成本率 5&#xff09; 期间费用率 好的&#xff0c;我将通过一个假设的案例&#xff08;某公司2023年数据&#xff09;逐步解释这些财务指标&#xff0c;并用具体数字演示计算…

PISI:眼图1:眼图相关基本概念

0 英文缩写 TIE&#xff08;Time Interval Error&#xff09;时间间隔误差&#xff0c;UI&#xff08;Unit Interval&#xff09;单位间隔PDF&#xff08;Probability Density Function&#xff09;概率密度函数BER&#xff08;Bit Error Rate&#xff09;误码率TJ&#xff08…

前端八股 CSS 2 选择器

选择器功能&#xff1a;选中特定 DOM节点进行渲染 原始方法 getElementById() getElementByName() 现在方法选择器 分类&#xff1a; id选择器 类选择器 标签选择器 逻辑与选择器 其他类型选择器&#xff1a; 伪类选择器&#xff1a; :link&#xff1a;未被访问的链接…

算法竞赛进阶指南.闇の連鎖

目录 题目算法标签: 树上差分, L C A LCA LCA, 倍增思路代码 题目 352. 闇の連鎖 算法标签: 树上差分, L C A LCA LCA, 倍增 思路 对于一个无向图, 第一次切断树边, 第二次切非树边, 一共多少种方案使得图不连通, 点数和边数都很大, 时间复杂度不能是 O ( n 2 ) O(n ^ 2…

ActiveMQ 与其他 MQ 的对比分析:Kafka/RocketMQ 的选型参考(二)

ActiveMQ、Kafka 和 RocketMQ 详细对比 性能对比 在性能方面&#xff0c;Kafka 和 RocketMQ 通常在高吞吐量场景下表现出色&#xff0c;而 ActiveMQ 则相对较弱。根据相关测试数据表明&#xff0c;Kafka 在处理大规模日志数据时&#xff0c;单机吞吐量可以达到每秒数十万条甚…

Electron 从零开始:构建你的第一个桌面应用

&#x1f5a5;️ Electron 从零开始&#xff1a;构建你的第一个桌面应用 Electron 是一个可以使用 HTML、CSS 和 JavaScript 构建跨平台桌面应用的框架。它将 Chromium 和 Node.js 融合到一个环境中&#xff0c;使 Web 开发者也能轻松开发原生桌面应用。 &#x1f680; 什么是 …

相向双指针-16. 最接近的三数之和

16. 最接近的三数之和 题目描述思路讲解代码展示复杂度分析相关标签 题目描述 思路讲解 思路和 15. 三数之和 类似&#xff0c;排序后&#xff0c;枚举 nums[i] 作为第一个数&#xff0c;那么问题变成找到另外两个数&#xff0c;使得这三个数的和与 target 最接近&#xff0c;…

C 语 言 - - - 文 件 操 作

C 语 言 - - - 文 件 操 作 文 件文 件 名文 件 操 作fopenfclose 文 件 的 顺 序 读 写fputcfgetcfputsfgetsfprintffscanffwritefread 流文 件 的 随 机 读 写fseekftellrewind 总结 &#x1f4bb;作 者 简 介&#xff1a;曾 与 你 一 样 迷 茫&#xff0c;现 以 经 验 助 你…

Walrus 与 Pudgy Penguins 达成合作,为 Web3 头部 IP 引入去中心化存储

以将深受喜爱的数字藏品赋予生命而闻名的 IP 与品牌开发公司 Pudgy Penguins&#xff0c;现已集成 Walrus&#xff0c;用于存储和管理其日益增长的数字媒体资源库&#xff0c;包括在其产品和社区体验中使用的贴纸和 GIF。团队将率先通过 Tusky&#xff08;Walrus 的用户友好型文…

2019ICPC陕西省赛暨陕西邀请赛题解 BCDEF HIJKL

共111支队伍&#xff0c;获奖情况&#xff08;大概&#xff09; 铜牌66 —— 3 296 银牌33 —— 4 391 金牌 11 —— 6 808 题目难度&#xff08;过题&#xff09;L F E B C I J D K H Problem - L - Codeforces 思路&#xff1a;注意到答案是连乘&#xff0c;只要有0…

5块钱的无忧套餐卡可以变成流量卡吗

电信的 5 块钱无忧套餐卡理论上可以变成流量卡&#xff0c;但会受到一些条件限制&#xff0c;以下是具体介绍&#xff1a; 中国电信无忧卡简介 中国电信无忧卡是电信推出的低月租套餐&#xff0c;月租仅 5 元&#xff0c;包含 200M 国内流量、来电显示和 189 邮箱&#xff0c;全…

SpringBoot校园失物招领平台源码开发实现

概述 实用的​​SpringBoot校园失物招领平台​​完整项目源码&#xff0c;帮助开发者快速构建校园失物招领系统。该项目采用SpringBootVue前后端分离架构&#xff0c;包含完整的注册登录、信息发布、认领管理等模块&#xff0c;是学习企业级项目开发的优秀范例 主要内容 1. …

如何在纯C中实现类、继承和多态(小白友好版)

基本实现原理 /* 通过结构体函数指针模拟类 */ typedef struct {// 成员变量int x; // 成员方法&#xff08;函数指针&#xff09; void (*print)(void* self); } MyClass;/* 成员函数实现 */ void my_print(void* self) {MyClass* obj (MyClass*)self;p…

51单片机入门教程——每个音符对应的重装载值

前言 本教程基于B站江协科技课程进行个人学习整理&#xff0c;专为拥有C语言基础的零基础入门51单片机新手设计。既帮助解决因时间差导致的设备迭代调试难题&#xff0c;也助力新手快速掌握51单片机核心知识&#xff0c;实现从C语言理论到单片机实践应用的高效过渡 。

股票单因子的检验方法有哪些?

股票单因子的检验方法主要包括以下四类方法及相关指标&#xff1a; 一、统计指标检验 IC值分析法 定义&#xff1a;IC值&#xff08;信息系数&#xff09;衡量因子值与股票未来收益的相关性&#xff0c;包括两种计算方式&#xff1a; Normal IC&#xff1a;基于Pearson相关系数…

洛谷 P8606 [蓝桥杯 2013 国 B] 高僧斗法 博弈论

题目 传送门 P8606 [蓝桥杯 2013 国 B] 高僧斗法 - 洛谷 思路 这个题就比较考验博弈的基本题型和转换能力了&#xff1b; 这个题是nim博弈>阶梯博弈 再将小和尚的移动转化为阶梯上石子的移动&#xff1a;两个小和尚之间可以移动的距离&#xff0c;看做阶梯上的石子&…