大模型交叉研讨课目录

链接: 大模型交叉研讨课

课程安排

第一部分:大模型基础

  • 第一节:自然语言处理基础知识 【6月27日】
  • 第二节:神经网络基础知识 【6月29日】
  • 第三节:Transformer与预训练模型 【7月1日】

第二部分:大模型技术

  • 第四节:Prompt Tuning, Delta Tuning 背景以及技术【7月4日】
  • 第五节:BMInf, BMTrain,BMCook相关背景和技术和使用【7月6日】
  • 第六节:基于大模型的文本理解与生成解决方案【7月8日】

第三部分:大模型交叉应用

  • 第七节:大模型X生物医学 【7月11日】
  • 第八节:大模型X法律智能 【7月13日】
  • 第九节:大模型X脑科学 【7月15日】


Transformers for NLP 第一章

第一章 What are Transformers?

工业4.0

这一章,作者认为Transformers 是工业4.0这个观点进行了阐述。

An Industry 4.0 project manager can go to OpenAI’s cloud platform, sign up, obtain an API key, and get to work in a few minutes. A user can then enter a text, specify the NLP task, and obtain a response sent by a GPT-3 transformer engine. Finally, a user can go to GPT-3 Codex and create applications with no knowledge of programming. Prompt engineering is a new skill that emerged from these models.

首先是云平台,然后提供API访问 包括像Codex都是,只要大模型提供了云API 都算是工业4.0 。 工业4.0 其实是数据驱动的人工智能型的网络化“智能工厂”,确实现在类似的API,其实还没有进入工业领域。

围绕现在transformers这个模型,其实建立起来的是foudation models,算是模型基础设施,后面这种基础设施也只有大厂会来做。

AI 的新范式,感觉是以基础大模型+微调 组成的。 这确实算是一种新的颠覆。

生成代码的Codex

输入:

输出的代码:

工业4.0 AI的角色

  1. API – 大模型
  2. 库 – 开源库
  3. 训练和微调 – 提供计算,训练和微调服务
  4. 开发技巧 – 模型落地

Transformers for NLP笔记

版本:Transformers for Natural Language Processing_Build, train, and fine-tune deep neural network architectures for NLP with Python, PyTorch, TensorFlow, BERT, and GPT-3 2nd Edition

官方代码: https://github.com/Denis2054/Transformers-for-NLP-2nd-Edition

目录:

  • Chapter 1: What are Transformers?
  • Chapter 2: Getting Started with the Architecture of the Transformer Model
  • Chapter 3: Fine-Tuning BERT Models
  • Chapter 4: Pretraining a RoBERTa Model from Scratch
  • Chapter 5: Downstream NLP Tasks with Transformers
  • Chapter 6: Machine Translation with the Transformer
  • Chapter 7: The Rise of Suprahuman Transformers with GPT-3 Engines
  • Chapter 8: Applying Transformers to Legal and Financial Documents for AI Text Summarization
  • Chapter 9: Matching Tokenizers and Datasets
  • Chapter 10: Semantic Role Labeling with BERT-Based Transformers
  • Chapter 11: Let Your Data Do the Talking: Story, Questions, and Answers
  • Chapter 12: Detecting Customer Emotions to Make Predictions
  • Chapter 13: Analyzing Fake News with Transformers
  • Chapter 14: Interpreting Black Box Transformer Models
  • Chapter 15: From NLP to Task-Agnostic Transformer Models
  • Chapter 16: The Emergence of Transformer-Driven Copilots

08.DPU网络开发SDK—DPDK(七)

接上次内容继续对rte_eal_init()所做的工作进行分析。
 
24. 内存初始化
24.2. 内存分配
调用eal_memalloc_init()来处理内存分配,前半部分根据进程是primary还是secondary走不同的流程,后半部分两者相同。

前后两个初始化过程中,用到了一个特殊的func,rte_memseg_list_walk(),该func的传入参数是一个rte_memseg_list_walk_t类型的函数指针及void *通用指针。在list_walk()中,会对rte_config.mem_config.memsegs列表中每一个memseg list依次调用函数指针指向的函数,且保证了整个过程中是在mem_config.memory_hotplug_lock锁的保护下进行的。

  • 以secondary方式
通过list_walk()来调用secondary_msl_create_walk()来为每个memseg list分配内存,该func中,根据primary的memseg list的大小,初始化一个local_memsegs结构,初始化还是调用rte_fbarray_init()来实现。primary的memseg list的大小从mem_config.memsegs获取到。

  • 以primary方式
该过程中,通过test_memfd_create执行memfd_create系统调用,测试当前系统是否支持创建匿名的内存共享,检查结果根据当前系统的一些配置情况决定是否以错误退出。

分primary和secondary之后,不管哪种方式初始化,都会执行fd_list_create_walk()。create_walk()对每个memseg list调用alloc_list(),alloc_list()会初始化文件描述符列表数组fd_list,每个memseg list对应一个数组项,数组项中会指向一块内存,用于存储文件描述符,这里的文件描述符即为匿名内存共享文件的描述符。

24.3. 初始化大页
初始化大页同样分primary和secondary

  • 以primary方式
调用rte_eal_hugepage_init(),如果internal_config设置了legacy_mem,那么调用eal_legacy_hugepage_init(),否则调用eal_dynmem_hugepage_init()。

 A. eal_dynmem_hugepage_init()
对于每一种大小类型的大页,确定好每个socket上页面的数量;统计出每个numa node上的内存大小;根据这些信息调用eal_dymem_calc_num_pages_per_socket()最终确定每种大小类型的页面的数量。

确定好这些信息之后,多次调用eal_memalloc_alloc_seg_bulk()来映射页面,该func通过list_walk()调用alloc_seg_walk()来完成这些工作。

B. eal_legacy_hugepage_init()
分为两种情况执行,一种禁用hugetlbfs情况下,另一种是在启用情况下。
 
a. 禁用hugetlbfs
此时允许的内存大小为64GB,页面大小为4KB,以此得出所需要的一个页面数量之后,调用eal_memseg_list_init_named()来重新初始化mem_config.memsegs[0]这个memseg list。然后通过eal_memseg_list_alloc()间接调用eal_get_virtual_area()为memseg分配虚拟地址,下一步通过mmap()系统调用创建匿名映射并获得匿名映射地址addr,接下来通过eal_memseg_list_populate()填充mem_config.memsegs[0]这个memseg list,以addr为基准计算出每个memseg的地址,填到相应的结构体中。
 
b. 启用hugetlbfs
首先统计出用了哪几种大小类型的大页内存,并且计算出总的大页内存页面数量,分别存放在used_hp数组和nr_hugepages当中。接下来开辟一块内存tmp_hp,用于存放nr_hugepages个struct hugepage_file结构,hugepage_file结构用于存放一些信息,比如该大页被映射到进程地址空间的哪个虚拟地址,大页物理地址是多少,所属socket_id是多少。

接下来,对于每一种页面大小类型的大页,做如下操作:

1.调用map_all_hugepages()映射该大小类型的所有大页,具体做法是调用open()打开大页在/sys文件系统中的文件,然后mmap()之后获取一个虚拟地址,并记录在结构体当中。

2.如果启用了物理地址,且IOVA的模式不是VA,那么调用find_physaddrs()获取到每个大页的物理地址并保存下来,否则调用set_physaddrs()设定一个伪物理地址。

3.调用find_numasocket()确定每个大页所属的socket_id。

4.根据物理地址将tmp_hp进行排序。

接下来根据tmp_hp中的信息,统计出每个socket每种大小类型的大页的数量,更新这些信息更新到internal_config.hugepage_info结构体当中,并最终确定每个socket下大页的数量。

接下来调用create_shared_memory()创建一个共享文件,大小为nr_hugepages个struct hugepage_file结构体,路径为/var/run/dpdk/rte/hugepage_data;接下来调用copy_hugepages_to_shared_mem()将该进程中分配到的大页信息写入到该文件当中。需要指出的是,到此为止所需要分配的内存就分配完了,后续不会再根据需要再额外分配大页内存,即使在DPDK进程运行过程中遇到内存耗尽的情况,所以在最后的收尾工作中,会将一些不需要的memseg list做释放处理。

  • 以secondary方式
调用rte_eal_hugepage_attach()来实现,同样分为是否设置了lagacy_mem,分别调用eal_legacy_hugepage_attach()和eal_hugepage_attach()

A. eal_legacy_hugepage_attach()
打开primary进程创建的文件/var/run/dpdk/rte/hugepage_data,并读取相应的信息,该文件的是多个hugepage_file结构体。对于每一个结构体中包含的信息,通过mmap()将大页内存还原到当前secondary进程当中,并以此初始化memseg list。

B. eal_hugepage_attach()
调用eal_memalloc_sync_with_primary(),该func会调用sync_walk()。sync_walk()会根据primary进程中的memseg list信息初始化自己的memseg list。sync_walk()会调用sync_existing()去打开/sys文件系统中的大页文件去确认已经被primary分配的内存和未被primary分配的内存跟memseg list中的信息是一致的,在确保一致的情况下才可以进行后续工作。
未完待续… 
往期回顾:
07.DPU网络开发SDK—DPDK(六)
06.DPU网络开发SDK—DPDK(五)
05.DPU网络开发SDK—DPDK(四)

07.DPU网络开发SDK—DPDK(六)

上次内容继续对rte_eal_init()所做的工作进行分析。
 
  1. 大页内存配置
internal_conf中的no_hugetlbfs指明是否禁用大页内存,通过命令行参数”–no-huge”设置禁用,默认情况下大页内存是开启的。DPDK根据进程是primary还是secondary的调用不同的初始化过程来初始化大页内存。
  • 按照primary方式初始化
调用eal_hugepage_info_init()来初始化primary进程。
该func首先调用hugepage_info_init()来初始化大页信息,首先遍历/sys/kernel/mm/hugepages中每个名称以”hugepages-“开头的目录,这种目录每个都代表了一种大小的页面,从目录名称中即可获得大页的大小,如hugepages-1048576kB代表1GB大小的页面。遍历过程中,根据目录名称获取到大页内存页面大小之后,接下来检查大页是否被正确挂载。打开/proc/mounts文件,查找到fstype为hugetlbfs类型的挂载项,获取到挂载点;如果没有挂载点,那么会寻找下一个大小类型的大页。找到挂载点之后,会调用calc_num_pages()计算页面数量。
需要额外注意的是,对于arm架构,可以支持4种页面大小类型,其他架构则只支持3种页面类型,多出的页面大小类型不做处理。多种符合要求的大页类型经过分析之后,相关信息会存放在internal_config的hugepage_info数组中。
hugepage_info_init()之后,如果是不共享文件模式(internal_config中的no_shconf置位),那么初始化过程就到此为止了,如果是共享模式,需要额外完成如下工作:通过调用create_shared_memory()在/var/run/dpdk/rte目录下创建hugepage_info文件,并通过mmap()将文件映射到DPDK进程的虚拟地址空间,之后将internal_config的hugepage_info数组拷贝到该文件中。
  • 按照secondary方式初始化
调用eal_hugepage_info_read()来初始化secondary进程,该func打开primary进程创建的/var/run/dpdk/rte目录下的hugepage_info文件,将文件中的信息拷贝到internal_config结构中的hugepage_info数组当中。
  1. 日志初始化
调用rte_eal_log_init()来初始化文件,该func中调用系统调用fopencookie和openlog来初始化日志文件。
  1. VFIO初始化(可选)
VFIO是否进行初始化由DPDK编译时是否开启了VFIO_PRESENT编译选项决定,开启了该编译选项时,调用rte_eal_vfio_setup()来初始化VFIO。初始化过程主要是判断当前系统中是否存在vifo模块。
  1. 内存域初始化
rte_eal_memzone_init()初始化的是rte_config中的mem_config下的memzone成员。同样根据DPDK进程是primary还是secondary分为不同的初始化过程。
  • 按照primary方式初始化
调用rte_fbarray_init()来初始化primary进程的memzone。DPDK中rte_memzone结构体是表示memzone的结构,需要为其分配内存空间;分配内存空间之前需要确定空间大小;DPDK允许RTE_MAX_MEMZONE(默认值2560)个内存域,那么就需要sizeof(rte_memzone) * RTE_MAX_MEMZONE大小的内存空间;同时还需要一个位图结构来表示这些内存域的使用情况,cal_data_size()完成了上述的计算工作。
确定完需要的内存大小之后,通过eal_get_virtual_area()确定一个虚拟地址data作为rte_memzone结构体的存储地址。确定好地址之后,接下来会根据是否设置了no_shconf对data进行不同的处理:如果是非共享模式,那么需要在虚拟地址data上创建一个匿名的内存映射;如果是共享的,会在/var/run/dpdk/rte目录下创建一个名称为fbarray_memzone的文件,并将文件通过mmap映射到虚拟地址data上。上面提到的一些信息,会存放在一个mem_area类型的结构体当中,并插入到模块全局列表mem_area_tailq中;另外还会存放在mem_config下的memzone成员当中。
  • 按照secondary方式初始化
调用rte_fbarray_attach()来初始化secondary进程的memzone,部分过程和rte_fbarry_init()相同,但是会直接打开fbarray_memzone的文件将该文件mmap()到虚拟地址空间data上。
  1. 内存初始化
调用rte_eal_memory_init()来初始化内存配置,分为多个步骤进行。
24.1. 内存段初始化
首先调用rte_eal_memseg_init()来初始化memseg。初始化memseg之前,需要将当前进程的资源限制进行下修改,更改可打开文件的最大数量。初始化memseg同样按照进程是primary还是secondary分别执行不同的初始化过程。
  • 按照primary方式初始化
编译DPDK时,会通过宏定义指定编译的系统架构为32位还是64位,这也决定了memseg的初始化方式的不同。
以64位系统初始化memseg_primary_init()为例,首先会初始化一个本地的结构体memtype的数组,结构体内包含hugepagesize和socket_id两个值,也就是说数组大小n_memtypes为前面统计出的大页内存种类数量*主机socket数量。memtype数组信息填充之后,计算出一些内存大小限制条件:通过宏定义RTE_MAX_MEM_MB(值为512GB)、RTE_MAX_MEM_MB_PER_TYPE(值为64GB)和n_memtypes确定单种类内存的大小限制max_mem_per_type和总的内存大小限制max_mem;通过RTE_MAX_MEMSEG_LISTS和n_memtypes确定每种memtype的segment数量。
接下来需要为每种memtype创建segment list,针对每种类型,需要将下列内容列入考虑范围后,得出一个精确的segment大小。
  • 该memtype可用内存总量
  • 每个segment允许的内存总量
  • 适配内存总量需要的segment数量
  • memtype允许的segment数量
  • 每个segment list允许的segment数量
  • 允许创建的segment list数量
确定好这些限制之后,调用eal_memseg_list_init()初始化每一个memseg list,该func最终是调用rte_fbarray_init()来实现初始化;然后是调用eal_memseg_list_alloc()来分配空间,该func最终是调用eal_get_virtual_area()来实现虚拟地址的分配。
  • 按照secondary方式初始化
调用memseg_secondary_init()来初始化memseg,该func中首先调用rte_fbarray_attach()来实现从文件获取primary进程memseg分配情况,然后通过调用eal_memseg_list_alloc()并最终调用eal_get_virtual_area()来分配虚拟内存空间。出现的几个func在前面memzone的初始化过程中已经出现过,这里不再具体说明。
 
内存初始化过程很长,未完待续……
 
往期回顾:
06.DPU网络开发SDK—DPDK(五)
05.DPU网络开发SDK—DPDK(四)
04.DPU网络开发SDK—DPDK(三)