支持AMD GPU的llm.c

anthonix/llm.c: LLM training in simple, raw C/HIP for AMD GPUs (github.com)

llm.c for AMD devices

This is a fork of Andrej Karpathy's llm.c with support for AMD devices.

性能

在单个7900 XTX显卡上使用默认设置,目前的训练步骤耗时约为79毫秒,相比PyTorch的夜间版本(2.4.0.dev20240513)的约97毫秒,以及tinygrad的约440毫秒来说,表现更优。

对于多GPU训练,在装有四个7900 XTX显卡的机器上,吞吐量达到了每秒约210,000个令牌。

更新(2024年5月28日):在单个7900 XTX显卡上,快速注意力分支的训练步骤时间已经降低到58.340831毫秒,或者在四个7900 XTX显卡上达到了每秒318,777个令牌的吞吐量。目前正在研究双缓冲技术以进一步推动性能提升。

状态

  • train_gpt2_fp32(基线,最小改动):使用32位浮点数(FP32)训练GPT-2模型(基线版本,仅进行最小改动)
  • train_gpt2 with BF16(基线,最小改动):使用半精度浮点数(BF16)训练GPT-2模型(基线版本,仅进行最小改动)
  • train_gpt2 with BF16 and multiple GPUs:使用半精度浮点数(BF16)并在多个GPU上训练GPT-2模型
  • RDNA3 优化内核(进行中):针对RDNA3架构优化的内核(仍在开发中)
  • CDNA3 优化内核:针对CDNA3架构优化的内核(具体状态未提及)

快速入门(AMD目标)

安装ROCm 6.1.1,检出仓库,并执行以下步骤:

  1. pip install -r requirements.txt (安装所需的依赖项)
  2. python prepro_tinyshakespeare.py (预处理tinyshakespeare数据集)
  3. export HF_ENDPOINT=https://hf-mirror.com
  4. python train_gpt2.py ((此步骤可能用于生成某种训练数据或配置,但具体细节未在给定指令中明确))
  5. make train_gpt2amd (编译AMD特定版本的GPT-2训练程序)

ROCm 6.0.2报错:

ld.lld: error: unable to find library -ldevice_gemm_operations
ld.lld: error: unable to find library -ldevice_other_operations
ld.lld: error: unable to find library -lstdc++
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:285:train_gpt2amd] 错误 1

不知道ROCm 6.1.1是否能编译成功。

 6. ./train_gpt2amd (运行AMD特定版本的GPT-2训练程序)

[原始README]

karpathy/llm.c

在简单、纯C/CUDA中进行LLM(大型语言模型)训练。无需245MB的PyTorch或107MB的cPython。在单个文件llm.c/train_gpt2.c中,使用CPU和fp32(32位浮点数)训练GPT-2大约需要1,000行干净的代码,而在llm.c/train_gpt2.cu中使用GPU训练大约需要3,000行代码(增加了CUDA内核)。代码立即编译并运行,它与PyTorch的参考实现完全匹配,并且当前速度略快于(编译后的)PyTorch(使用bf16、torch编译和flash attention)。我选择GPT-2作为第一个工作示例,因为它是LLM的鼻祖,也是现代堆栈首次结合在一起的例子。

我们当前的目标是复现GPT-2。要了解当前正在进行的工作的概述,请参阅最新的State of the Union帖子。

2024年5月28日更新:一个有用的近期帖子可能是“在llm.c中用90分钟和20美元复现GPT-2(124M)”,我在其中详细说明了从零开始复现124M/350M模型的GPT-2微系列的步骤。展示启动命令的文件本身是run124M.sh和run350M.sh。

我希望这个仓库只维护C和CUDA代码。这个仓库到其他语言的移植非常受欢迎,但应该在单独的仓库中完成,然后我很乐意在下面的“显著分支”部分链接到它们,就像我在llama2.c分支中所做的那样。

快速入门(GPU,速度慢但稳定且适合学习)

对于“我不在乎其他任何事情,我只想训练,并且我有GPU”的这部分用户。请运行以下命令:

pip install -r requirements.txt
python dev/data/tinyshakespeare.py
python train_gpt2.py
make train_gpt2fp32cu
./train_gpt2fp32cu

以上命令(1)会下载tinyshakespeare数据集,并使用GPT-2的Tokenizer进行分词处理,(2)下载并保存GPT-2(124M)的权重,(3)在C/CUDA中从这些权重初始化,并在tinyshakespeare数据集上使用AdamW优化器进行一轮(epoch)的训练(使用批量大小4,上下文长度1024,总共74步),评估验证损失,并生成一些文本样本。请注意,在这个快速入门中,我们使用的是CUDA代码的fp32版本train_gpt2_fp32.cu。在下一节中,我们将介绍当前“主流”的train_gpt2.cu,它使用混合精度,运行速度大约快2倍。

快速入门(GPU,最前沿的优化)

我想看到它运行得更快。在这种情况下,切换到我们最主要的、优化度最高的 train_gpt2.cu。运行如下命令:

pip install -r requirements.txt
python dev/data/tinyshakespeare.py
python train_gpt2.py
make train_gpt2cu
./train_gpt2cu

如果你额外安装了cuDNN(请参见下面的CUDA部分),你可以通过flash attention实现更快的速度。调整make命令,如下编译带有cudnn/flash attention的版本:

make train_gpt2cu USE_CUDNN=1
./train_gtp2cu

这段话的意思是,如果你已经安装了cuDNN,那么在编译和运行一个名为train_gpt2cu的程序时,可以通过设置USE_CUDNN=1来启用cuDNN的支持,从而利用cuDNN提供的加速功能来提高程序的运行速度。这里的make是一个构建工具,用于自动化编译过程,而./train_gpt2cu则是运行编译后的程序。
请注意,默认的批量大小非常小(4)。如果你的GPU有足够的内存,我建议你将其增加到例如32:

./train_gtp2cu -b 32

我的标准单GPU "生产" 运行(例如使用A100 40GB)不是训练TinyShakespeare,而是训练TinyStories,示例如下:

python dev/data/tinystories.py
make train_gtp2cu USE_CUDNN=1
./train_gtp2cu -i dev/data/tinystories/TinyStories_train.bin \-j dev/data/tinystories/TinyStories_val.bin \-v 250 -s 250 -g 144 -o stories.log -b 32

-i 标志是输入数据的通配符模式,`-j` 是验证数据。另外,我将验证损失和采样的频率减少到每250步,并且在采样阶段采样144个tokens(大约能装下一篇故事),批量大小为32。
如果你想要训练实际的、真实的预训练数据,查看最近添加的对 fineweb数据集 的支持。与上面的数据集不同,这里的训练/验证tokens 不是放在一个.bin文件中,而是现在有多个数据分片。这里有一个示例:

# 将FineWeb数据以1亿个标记的分片写入到dev/data/fineweb10B
python dev/data/fineweb.py -s 100000000
# 编译并运行
./train_gtp2cu -i "dev/data/fineweb10B/fineweb_train_*.bin" \-j "dev/data/fineweb10B/fineweb_val_*.bin" \-v 250 -s 250 -g 144 -o fineweb.log -b 32

其中,你会注意到使用了通配符 * 来匹配所有的训练分片。

快速入门(多GPU)

很好,让我们更进一步。我们将使用MPI和NCCL来进行多GPU训练。上面部分的内容依然适用,但需要做以下改变:

# 安装MPI的示例:
sudo apt install openmpi-bin openmpi-doc libopenmpi-dev# 运行命令现在需要以 mpirun 开头:
mpirun -np <你机器上的GPU数量> ./train_gpt2cu

在最后的命令中,替换为你想要运行的GPU数量。上面部分讨论的所有标志在这里也适用。

快速开始(CPU)

“我是如此贫穷以至于连GPU都没有”的部分。你仍然可以进行训练!但你不会走得太远。你仍然可以微调一个GPT-2小模型(1.24亿参数模型)以输出像莎士比亚式的文本,作为示例:

pip install -r requirements.txt
python dev/data/tinyshakespeare.py
python train_gpt2.py
make train_gpt2
OMP_NUM_THREADS=8 ./train_gpt2

上面的行(1)下载了tinyshakespeare 数据集,使用GPT-2的分词器对其进行分识,(2)下载并保存GPT-2(124M)的权重,(3)在C中从它们初始化并在tineshakespeare上训练40步骤使用AdamW(使用批量大小4,上下文长度只有64),评估验证损失,并抽取一些文本。诚实地讲,除非你有一个强大的CPU(并且可以在启动命令中增加OMP线程的数量),你在CPU上训练大型语言模型(LLMs)不会走得太远,但它可能是一个不错的演示/参考。

训练:更多细节

在`/dev/data/(dataset).py`的数据文件负责下载、分词并将分词保存到文件中。例如,当你运行:

python dev/data/tinyshakespeare.py

我们下载并分词tinyshakespeare数据集。这个输出看起来像这样:

writing 32,768 tokens to ./dev/data/tinyshakespeare/tiny_shakespeare_val.bin
writing 305,260 tokens to ./dev/data/tinyshakespeare/tiny_shakespeare_train.bin

.bin文件包含一个短的头部(1024字节),随后是一个流式的tokens以uint16格式,表明了用GPT-2分词器的分词id。更多数据集可以在`/dev/data`找到。
原则上,一旦我们得到了tokens,我们就准备在这里开始训练模型。然而,当前的代码还不能从零开始训练(很快就会加入),所以我们从OpenAI发布的预训练模型初始化训练并进行微调。为此,我们需要下载GPT-2的权重并将其作为我们可以在C语言中加载的检查点来保存。这就是当你运行以下脚本时发生的事:

python train_gpt2.py

你会认出这段代码,它来自nanoGPT,是一个简单的PyTorch中的GPT-2参考实现。这个脚本将下载GPT-2 (124M)模型,对单批数据进行了10次迭代的超过拟合,运行了几步生成,并且更重要的是它将保存三个文件:1)`gpt2_124M.bin`文件,它包含了原始模型权重以便在C语言中加载,2)`gpt2_124M_debug_state.bin`文件,这也包含了更多的调试状态:输入,目标,逻辑和损失(对于调试和单元测试很有用),最后3)`gpt2_tokenizer.bin`文件,它存储了GPT-2分词器的词汇表,将分词id转换为UTF-8编码字符串片段的字节序列。文件还保存了上述的fp32版本,以及它们的bfloat16版本以供混合精度训练。我们现在可以用这些模型权重来初始化并继续在原始C语言中训练。然后我们用`make`命令来编译训练程序。目前有三个并行实现:

# 简单的,CPU,参考代码版本
make train_gpt2
# 单GPU fp32 CUDA版本
make train_gpt2fp32cu
# 多GPU混合精度CUDA版本
make train_gpt2cu

你可以查阅`Makefile`及其注释。它会尝试自动探测很多工具和库(例如:cuDNN, OpenMP, OpenMPI, nvcc),你要尽量获得尽可能多的勾号。比如当我在我配置完善的机器上运行`make train_gpt2cu USE_CUDNN=1`,我们看到:

✓ cuDNN found, will run with flash-attention
✓ OpenMP found
✓ OpenMPI found, OK to train with multiple GPUs
✓ nvcc found, including GPU/CUDA support

有些人在Ubuntu上编译时遇到问题,请查看Issue 19,简而言之就是你想修改`CFLAGS`:

# 首先尝试这个
CFLAGS="-Ofast -fno-finite-math-only -Wno-unused-result -march=native" make train_gpt2
# 其次尝试这个
CFLAGS="-O3 -Wno-unused-result -march=native" make train_gpt2

一旦编译好了二进制文件,我们就可以运行它。例如最简单的CPU参考版本运行如下:

OMP_NUM_THREADS=8 ./train_gpt2

你应该根据你的CPU拥有多少核心来调整线程数量。该程序将加载模型权重、tokens,它将运行一个微调循环数次与Adam lr 1e-4,然后从模型中生成一个样本。这个文件很可读,你应该看一看。简单来说,就是所有层的前向和后向传递的实现,并且它们被串接在一个大的、手动的、前向/后向/更新循环中。输出看起来像这样在我的MacBook Pro(苹果硅 M3 Max)上:
 

[GPT-2]
max_seq_len: 1024
vocab_size: 50257
num_layers: 12
num_heads: 12
channels: 768
num_parameters: 124439808
train dataset num_batches: 1192
val dataset num_batches: 128
num_activations: 73323776
val loss 5.252026
step 0: train loss 5.356189 (took 1452.121000 ms)
step 1: train loss 4.301069 (took 1288.673000 ms)
step 2: train loss 4.623322 (took 1369.394000 ms)
step 3: train loss 4.600470 (took 1290.761000 ms)
... (trunctated) ...
step 39: train loss 3.970751 (took 1323.779000 ms)
val loss 4.107781
generating:
---
Come Running Away,
Greater conquer
With the Imperial blood
the heaviest host of the gods
into this wondrous world beyond.
I will not back thee, for how sweet after birth
Netflix against repounder,
will not
flourish against the earlocks of
Allay
---

我喜欢Netflix的出现,很明显模型的训练过往仍在影响它。我没有尝试调整微调的超参数,所以这个结果很可能还可以大幅度提高。我还注意到,不同的平台(例如MacOS/Linux)将会(遗憾地)给出非常微小的不同结果,所以可能不要期望得到上文提供的确切的数字或生成结果。

最后,代码还在变动中。如果发生任何你没预料到或之前运行正常的奇怪事情,请尝试`git pull`,重新运行所有上面的命令,回到这个README文件参考,等等。

测试

我还附上了一个简单的单元测试,以确保我们的 C 代码与 PyTorch 代码一致。以 CPU 为例,编译并且执行如下:

make test_gpt2
./test_gpt2

这将加载 gpt2_124M_debug_state.bin 文件,执行一个前向传递,与 PyTorch 参考实现比较 logits 和 loss,然后进行 10 次迭代的 Adam 训练确保损失与 PyTorch 匹配。要测试 GPU 版本,我运行:

# fp32 测试(不支持 cudnn)
make test_gpt2cu PRECISION=FP32 && ./test_gpt2cu
# 混合精度 cudnn 测试
make test_gpt2cu USE_CUDNN=1 && ./test_gpt2cu

教程

我在这里附上了一个非常小的教程,在 doc/layernorm/layernorm.md。这是一个实现 GPT-2 模型的单层,layernorm 层的简单分步指导。这是理解 C 中是如何实现层的一个好的起点。

CUDA

整个训练循环也在一个文件中使用纯CUDA实现,但是内核的优化还在进行中。目前,我们的速度略微超过了PyTorch Nightly的速度。我们组织代码的方式是,在`dev/cuda`文件夹中收集了越来越多的复杂程度递增的内核,详见dev/cuda/README.md。然后,我们将最好的内核复制粘贴到单一训练文件`train_gpt2cu.cu`中的主要训练循环中。

WIP警告,2024年4月23日。我们合并了第一个版本的混合精度训练代码。我将fp32版本的检查点备份到包含`_fp32`文件名的单独文件中,并希望保留这个版本在仓库的根目录中,因为它1)不需要最新的CUDA,更有可能编译和更加便于移植,2)它更简单,并且充当参考。事实上,我们想让fp32版本朝着纯CUDA的方向发展(例如,默认情况下甚至不调用cuBLAS),用作教育参考,甚至可能是CUDA课程的一个内核。从现在开始,与速度有关的"主线"开发将转移到train_gpt2.cu文件,该文件包含混合精度训练。

在下面的描述中,我现在默认使用fp32版本,因为它当前更加便携和稳定,然后在最后我将介绍新的混合精度版本。

正确性。首先,我们可以做10次训练迭代并验证我们的代码是否与PyTorch完全匹配和再现数字:

make test_gpt2fp32cu
./test_gpt2fp32cu

这会打印出`overall okay: 1`。因此,前向激活、后向梯度和10次迭代的各个损失值都完全匹配。

训练。在单GPU上以fp32进行训练:

make train_gpt2fp32cu
./train_gpt2fp32cu

这将加载tiny_shakespeare数据集的验证和训练划分。在默认设置B=4,T=1024下,有8个验证批次和74个训练批次。该脚本目前配置为以1e-4的学习速率进行单轮微调,并在此过程中评估验证性能和生成样本,例如:

step 1/74: train loss 4.367631 (80.639749 ms)
step 2/74: train loss 4.031242 (77.378867 ms)
step 3/74: train loss 4.034144 (77.315861 ms)
step 4/74: train loss 3.859865 (77.357575 ms)
...
step 72/74: train loss 3.085081 (78.850895 ms)
step 73/74: train loss 3.668018 (78.197064 ms)
step 74/74: train loss 3.467508 (78.009975 ms)
val loss 3.516490
generating:
---
?Where will you go?
I take you wherefore I can, myself, and must.
I cast off my beak, that I may look him up on the point;
For on his rock shall he be opencast.<|endoftext|>My little nephew:
Keep on with me, my

这在我的A100上大约运行了~10秒。我们可以这样与naive PyTorch进行比较,我们开启了`torch.compile`和使用TensorCores,它使用的是tf32类型:

python train_gpt2.py --write_tensors 0 --sequence_length 1024 --batch_size 4 --compile 1 --tensorcores 1

编译(第一次迭代)大约需要~27秒,但之后在我的A100上目前的运行速度约为每次迭代~80ms。

混合精度。新的CUDA混合精度版本,未来大部分开发将在此进行,是train_gpt2.cu,以及它的测试test_gpt2.cu。在这里,许多计算以较低精度格式(fp16或bf16)进行,这使我们能够以非常快的速度运行(约为上面TF32性能的2倍)。注意,我描述的基线实现作为`fp32`,但更精确地说,实际上是`tf32`(TensorFloat32)。训练和测试的命令都一样,只需省略fp32部分:

make train_gpt2cu
./train_gpt2cumake test_gpt2cu
./test_gpt2cu

如果您有最新的CUDA,应该期望它可以编译OK,并且应该看到性能大幅改进。

Flash Attention。截至2024年5月1日,我们现在支持来自cuDNN的Flash Attention。因为cuDNN使编译时间从几秒增加到约一分钟,并且这个代码路径现在非常 新颖,目前默认情况下是禁用的。您可以通过以下方式编译来启用它:

make train_gpt2cu USE_CUDNN=1

这将尝试使用cudnn进行编译并运行。您必须在您的系统上安装cuDNN。通过apt-get安装的cuDNN安装说明将获取默认的cuDNN包集。对于最小安装来说,cuDNN dev包是足够的,例如在Ubuntu 22.04上为CUDA 12.x:

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update
sudo apt-get -y install libcudnn9-dev-cuda-12

除此之外,您还需要cuDNN前端,但这只是头文件。只需将仓库克隆到您的磁盘即可。如果您将其放在其他地方,将`CUDNN_FRONTEND_PATH=/path/to/your/cudnn-frontend/include`添加到`make`命令行中。

多GPU训练。截至2024年4月26日,现在还支持使用MPI和NCCL进行多GPU训练。确保您安装了MPI,例如在Linux上:

sudo apt install openmpi-bin openmpi-doc libopenmpi-dev

然后:

make train_gpt2cu
mpirun -np <GPU数量> ./train_gpt2cu

fp32版本的代码不支持多GPU。这是因为我们希望GPT-2 fp32版本成为CUDA优化课程的一个不错的教育终点。混合精度版本是我们进行前沿开发的版本,因此这是支持多GPU训练的版本。

实验/扫描

现在基本的 argparse 和日志功能已存在于 .cu 脚本中,我们可以开始进行第一轮学习率扫描。目前这还相当手动,但是下面记录了一个示例过程,展示了在一台拥有4个GPU的机器上针对TinyStories数据集进行学习率扫描的过程。在你当然已经使用 chmod u+x sweep.sh 命令赋予了sweep.sh脚本执行权限后,运行一个名为 sweep.sh 的shell脚本:

#!/bin/bashlearning_rates=(3e-5 1e-4 3e-4 1e-3)for i in {0..3}; doexport CUDA_VISIBLE_DEVICES=$iscreen -dmS "tr$i" bash -c "./train_gpt2cu -i data/TinyStories -v 250 -s 250 -g 144 -l ${learning_rates[$i]} -o stories$i.log"
done# 你可以使用以下命令关闭这些屏幕会话
# screen -ls | grep -E "tr[0-3]" | cut -d. -f1 | xargs -I {} screen -X -S {} quit

这个例子打开了4个screen会话,并使用不同的学习率运行四个命令。这会将所有损失写入日志文件 stories$i.log,你可以按照自己的意愿在Python中进行绘制。解析和绘制这些日志文件的一个快速例子可以在 dev/vislog.ipynb 中找到。

代码仓库理念

关于我希望这个代码仓库`llm.c`能够成为的几点想法:
首先,我希望`llm.c`能成为一个教学场所。举个例子,我们的`dev/cuda`文件夹是一个包含了各种手写、文档齐全的内核库,从最简单的内核开始,到更复杂/更快速的内核。如果您有带有不同权衡的新内核,请随时贡献至此。
话虽如此,我也希望`llm.c`能够非常快速,甚至在实际中用于训练网络。比如,首先,我们应该能复现大型GPT-2(1.6B)的训练过程。这需要我们整合各种最快的内核,包含使用如cuBLAS、cuBLASLt、CUTLASS、cuDNN等库。我同样认为这样做对于确立一个专家级的上限,并作为一种度量单位,具有教育意义。比如,你可以说你手写的内核速度达到了cuBLAS的80%等。然后你可以选择进行一个超快的运行,或者你可以选择 "拖放 "任何你想使用的手动内核,并用那些运行。
然而,作为一个限制,我希望保持根目录下的主线`llm.c`简单且可读。如果有一个PR能够改进性能2%,但它“花费了”500行复杂的C代码,可能还有一些非主流的第三方依赖,我可能会拒绝这个PR,因为复杂性不值得。具体的一个例子 - 让cuBLAS成为根训练循环的默认矩阵乘法是明智的:它让主线代码快了很多,它是一行易于理解的代码,而且是一个非常常见的依赖。在这一侧,我们可以在`dev/cuda`中有与cuBLAS竞争的手写实现。
最后,对于项目根目录中包含主要/默认文件的部分,我会对复杂性更加敏感。相比之下,`dev/`文件夹更像是一个草稿空间,供我们开发内核或类的库,分享有用或相关的或教育性代码,其中一些代码是可以接受的(局部)复杂性。

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

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

相关文章

Docker的安装、启动和配置镜像加速

前言&#xff1a; Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 而企业部署一般都是采用Linux操作系统&#xff0c;而…

【软件设计师】2022年上半年真题解析

​​冯诺依曼计算机体系结构的基本特点是&#xff1a; A. 程序指令和数据都采用二进制表示 - 这是正确的&#xff0c;因为冯诺依曼架构下的计算机使用二进制形式来表示和处理所有信息&#xff0c;包括指令和数据。 B. 程序指令总是存储在主存中&#xff0c;而数据则存储在高速…

IsoBench:多模态基础模型性能的基准测试与优化

随着多模态基础模型的快速发展&#xff0c;如何准确评估这些模型在不同输入模态下的性能成为了一个重要课题。本文提出了IsoBench&#xff0c;一个基准数据集&#xff0c;旨在通过提供多种同构&#xff08;isomorphic&#xff09;表示形式的问题&#xff0c;来测试和评估多模态…

算法(十三)回溯算法---N皇后问题

文章目录 算法概念经典例子 - N皇后问题什么是N皇后问题&#xff1f;实现思路 算法概念 回溯算法是类似枚举的深度优先搜索尝试过程&#xff0c;主要是再搜索尝试中寻找问题的解&#xff0c;当发生不满足求解条件时&#xff0c;就会”回溯“返回&#xff08;也就是递归返回&am…

enum4linux一键查询SMB信息(KALI工具系列十六)

目录 1、KALI LINUX简介 2、enum4linux工具简介 3、在KALI中使用enum4linux 3.1 目标主机IP&#xff08;win&#xff09; ​编辑 3.2 KALI的IP 4、操作示例 4.1 运行工具 4.2 列出用户名 4.3 提取用户名 4.4 使用自定义RID范围 4.5 列出组 4.6 列出共享文件夹 4.7…

网络监听技术

网络监听技术 网络监听概述网络监听环境 流量劫持网络环境共享式网络监听原理交换式网络监听交换机的工作方式交换网络监听&#xff1a;交换机集线器交换网络监听&#xff1a;端口镜像交换网络监听&#xff1a;MAC洪泛交换网络监听&#xff1a;MAC洪泛交换网络监听&#xff1a;…

动态SQL where, choose语句

where语句就一个<where>标签, 很简单, 不再过多赘述 接下来我们来看 choose语句的使用 其实choose语句就像java里的swith语句 , 如果语句前面的生效 , 后面的就不会生效了 可以定义查询的优先级

读人工智能时代与人类未来笔记19_读后总结与感想兼导读

1. 基本信息 人工智能时代与人类未来 (美)亨利基辛格,(美)埃里克施密特,(美)丹尼尔胡滕洛赫尔 著 中信出版社,2023年6月出版 1.1. 读薄率 书籍总字数145千字&#xff0c;笔记总字数39934字。 读薄率39934145000≈27.5% 1.2. 读厚方向 千脑智能 脑机穿越 未来呼啸而来 …

【工具】 MyBatis Plus的SQL拦截器自动翻译替换“?“符号为真实数值

【工具】 MyBatis Plus的SQL拦截器自动翻译替换"?"符号为真实数值 使用MyBatis的配置如下所示&#xff1a; mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl调用接口&#xff0c;sql日志打印如下&#xff1a; 参数和sql语句不…

顶底背离的终极猜想和运用

这几天圈内都在传底蓓离什么的。作为严肃的量化自媒体&#xff0c;我们就不跟着吃这波瓜了。不过&#xff0c;我一直很关注技术指标的顶背离和底背离&#xff0c;一直在追问它的成因如何&#xff0c;以及如何预测。 底蓓离把我目光再次吸引到这个领域来&#xff0c;于是突然有…

LitCTF 2024(公开赛道)——WP

目录 Misc 涐贪恋和伱、甾―⑺d毎兮毎秒 你说得对&#xff0c;但__ 盯帧珍珠 Everywhere We Go 关键&#xff0c;太关键了! 女装照流量 原铁&#xff0c;启动&#xff01; 舔到最后应有尽有 The love Web exx 一个....池子&#xff1f; SAS - Serializing Authent…

MySQL—函数—日期函数(基础)

一、引言 接下来讨论和学习关于函数的第三个方面——日期函数。 常见的MySQL当中的日期函数。 注意&#xff1a; 1、CURDATE()&#xff1a;cur&#xff1a;current 当前的&#xff0c;返回的是当前日期。 2、CURTIME()&#xff1a;当前时间。 3、NOW&#xff1a;当前的日期和…

政安晨【零基础玩转各类开源AI项目】:解析开源项目的论文:Physical Non-inertial Poser (PNP)

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 零基础玩转各类开源AI项目 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 本文解析的原始论文为&#xff1a;https://arxiv.org/…

力扣1143. 最长公共子序列

给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&#xff08;也可以…

打造你的专属Vue组件:基于FullCalendar超实用“日程任务管理组件”实战

打造你的专属Vue组件&#xff1a;基于FullCalendar超实用“日程任务管理组件”实战 在现代Web应用中&#xff0c;日程管理是一个常见而又关键的功能&#xff0c;它帮助用户高效安排和追踪日常任务及会议。Vue.js作为一个流行的前端框架&#xff0c;以其简洁的语法和强大的组件…

编译选项导致的结构体字节参数异常

文章目录 前言问题描述原因分析问题解决总结 前言 在构建编译工程时&#xff0c;会有一些对应的编译配置选项&#xff0c;不同的编译器&#xff0c;会有对应的配置项。本文介绍GHS工程中编译选项配置不对应导致的异常。 问题描述 在S32K3集成工程中&#xff0c;核1的INP_SWC…

JVM垃圾收集器和内存分配策略

概述 Java内存运行时数据区的程序计数器、虚拟机栈、本地方法栈3个区域会随着线程而产生&#xff0c;随线程而消失。这几个区域分配多少内存时在类结构确定下来即已知的&#xff0c;在这几个区域内就不需要过多考虑如何回收内存的问题&#xff0c;当方法结束或者线程结束时&am…

【spring】第一篇 IOC和DI入门案例

Spring到底是如何来实现IOC和DI的&#xff0c;那接下来就通过一些简单的入门案例&#xff0c;来演示下具体实现过程。 目录 前期准备 一、IOC入门案例 思路分析 代码实现 二、DI入门案例 思路分析 代码实现 总结 前期准备 使用IDEA创建Maven项目&#xff0c;首先需要配…

JAVAEE1

Web前端&#xff1a; 1.建立web开发的息维模式写代码不仅仅是为了实现某个功能&#xff0c;更是学习解决问题的思维方式 2.先使用&#xff0c;再理解&#xff0c;会导致刚开始比较懵&#xff0c;不知其所以然.切忌不可深陷其中&#xff0c; 3.涉及简单的软件工程的设计思想&…

SPWM载波调制方式-三电平杂记1

方法一&#xff1a; P2 O1 N0 方法二&#xff1a;双载波直接发波 方法三&#xff1a;负轴载波和调制波往上抬升1&#xff0c;得到使用同一个载波 在正半周在P和O切换&#xff0c;在下半轴式O和N切换