跳到主要内容

博客

代码人生:编织技术与生活的博客之旅

客户需求

1. 行政应用

这些应用文和公文都在中小学校的日常管理和教学工作中发挥着重要作用,规范了学校事务的沟通和操作。

  • 会议纪要: 记录会议内容和决议的重要文档,‌帮助参会人员回顾会议内容,‌明确工作任务和责任。‌
  • 请假申请:‌用于向上级领导请假并说明请假事由和请假时间。‌
  • 报销申请:‌向财务部门申请报销各类费用的文档。‌
  • 文件传真:‌快速传递文件和信息的沟通工具。‌
  • 安全管理制度:‌包括学校行政方面安全管理制度、‌学校消防安全管理制度、‌学校周边环境安全治理制度等,‌确保校园安全。‌
  • 学籍管理:‌负责学籍信息收集、‌汇总、‌校验、‌上报等工作,‌应用学籍系统开展日常学籍管理工作,‌确保学生学籍信息的真实、‌准确、‌完整。‌

这些文档不仅规范了中小学的日常行政管理流程,‌提高了工作效率,‌还保证了工作的准确性和可靠性,‌是中小学行政管理不可或缺的工具

中小学校范围内应用文和公文种类繁多,涵盖了各种日常管理、教育教学、学生事务等方面。以下是一些常见的应用文和公文类型:

1.1 应用文

1.通知:用于发布学校的各类信息,如放假安排、家长会通知等。 2.通告:告知全校师生某些重要事项,如安全通告、禁烟通告等。 3.请假条:学生或教师因事请假时使用。 4.借条:用于借用学校财产或图书馆借书时的凭据。 5.感谢信:用于向老师、家长或合作单位表示感谢。 6.检讨书:学生因违反纪律或规章制度写的自我反省书。 7.申请书:申请加入学校某个组织、社团或申请奖学金时所使用的文书。 8.证明:老师或学校为学生开具的各种证明,如在读证明、实习证明等。 9.总结报告:教学工作、学生会工作等结束时所作的总结。 10.会议记录:记录教师会议、家长会等内容。

1.2 与上级的公文

1.请示:向上级机关请示报告工作或请求批准某事项。 2.报告:向上级报告工作情况、阶段性成果或问题。 3.总结汇报:阶段性工作总结或专项工作完成后的汇报。 4.申请报告:例如申请拨款、申请设备等。 5.方案:提交的工作计划、活动方案或实施建议等。 6.调查报告:针对某些问题或事件进行调查后向上级提交的报告。

1.3 校内公文

1.会议纪要:记录、总结各类校内会议内容和决定。 2.工作计划:各部门学期、学年或具体项目的工作安排。 3.工作总结:各部门阶段性或专项工作的总结。 4.意见和建议:向学校提出改进建议或作出意见反馈的文书。 5.布告:校内发布的一些正式信息,如教师招聘公告、考试安排公告等。 6.批复:学校领导对请示、报告的回复。 7.规章制度:学校制定的各类管理制度和规定。 8.奖惩通报:对师生表彰或批评的通报。 9.红头文件:学校正式发布的各类重要文件。

2. 科研应用

2.1 论文助手

  • 论文资料收集:帮助搜集与论文相关的文献与资料。
  • 论文辅助阅读:论文辅助助手可以快速帮助完成读取分析。运用文档读取插件,可以上传文档分析或总结文章内容,帮助阅读文章并提取知识精华和关键点。
  • 论文写作:论文写作助手可以根据要求帮助快速完成论文写作。输入论文主题,即可生成论文大纲,根据生成的大纲,逐步生成每一章节的论文内容。

3. 教学应用

3.1 教学助手

  • 智能辅导与个性化学习

    • 智能答疑系统:为学生提供及时、准确的答疑服务,解答学习中的疑难问题。
    • 个性化学习平台:基于AI的学习平台能够根据学生的学习进度、知识掌握情况和学习习惯定制个性化学习计划,提供个性化的练习题和学习资源。
    • 自适应学习系统:通过分析学生的学习数据,实时调整学习内容和难度,以适应每个学生的学习节奏和需求。
  • AI辅助教学

    • 教学资源推荐:根据教学内容和目标,AI能够自动为教师推荐相关的教学资源、课程素材和教学案例。
    • 备课助手:备课助手可以在备课环节中辅助教师快速生成教学大纲及教案。应用可根据课程主题、重点及要求,收集网络相关资料,整理并生成备课所需的内容。
    • 智能批改作业:利用自然语言处理技术,AI系统可以帮助教师自动批改客观题和主观题,提供批改建议,减轻教师的工作量。
    • 课堂管理:智能课堂管理系统可以帮助教师实时监控课堂情况,记录学生出勤、表现,进行课堂互动评估等。
  • 智能评估与分析

    • 学习数据分析:通过收集和分析学生的学习数据,AI能够生成详细的学习报告,帮助教师了解学生的学习情况和存在的问题,进而调整教学策略。
    • 智能测评系统:基于大数据和AI技术,系统能够设计和实施各类学科测评,并对测评结果进行智能分析,提供详细的反馈和改进建议。
  • 语言学习与翻译

    • 智能翻译工具:在英语或其他语言课程中,智能翻译工具可以帮助学生理解外文资料,进行翻译和口语练习。
    • 语音识别与评分:通过语音识别技术,AI能够对学生的发音、语调进行分析和评分,提供改进建议。
  • 虚拟现实与增强现实

    • 虚拟现实(VR)教学:通过虚拟现实技术,学生可以身临其境地参与到历史事件、科学实验等各种虚拟环境中,增加学习的趣味性和互动性。
    • 增强现实(AR)教材:利用增强现实技术,教科书上的图片可以变成动态的3D模型,帮助学生更直观地理解复杂的概念和内容。
  • 机器人助教

    • 教育机器人:一些先进的教育机器人可以在课堂中扮演助教角色,进行知识讲解、互动问答,甚至帮助老师进行课堂管理。
    • 陪伴型机器人:这些机器人在课堂之外可以陪伴学生学习,进行一些简单的知识问答和互动,激发学生的学习兴趣。
  • 心理健康与行为分析

    • 智能心理辅导:AI系统能够通过分析学生的行为数据、情绪表达等,帮助识别学生的心理问题,提供心理健康建议和辅助性服务。
    • 行为分析与干预:通过分析学生在课堂中的表现和行为轨迹,AI能够帮助教师识别和管理学生的行为问题,提供个性化的辅导和干预策略。
  • 教育资源管理

    • 智能排课系统:利用AI技术,能够根据学生和教师的时间表、课程需求,自动生成最优的课程安排方案。
    • 资源调度与优化:AI系统可以帮助学校优化图书馆、计算机房、多媒体教室等资源的使用,提高资源利用效率。
  • 智能翻译:智能翻译助手可以帮助快速翻译外文文献、文章、资料。将文章内容复制输入,一键翻译为中文内容。

  • 试题生成:可输入考试科目并上传包含所需知识点的文档。系统通过分 析这些资料并且结合设定的要求,自动化地产生一系列试题。此外,生 成的试卷可以转化成电子格式,方便在线测试或电子提交。

  • 绘图助手:绘图助手可以帮助教师快速生成教学用图、PPT配图等,协助在课堂上对知识内容进行多元化表达。使用自然语言输入画面描述,快速生成图片。

  • 学生评价助手:输入“学生优点”、“学生不足”和字数要求,应用将结合训练的评语文档内容以及给出的要求快速生成出评语。

4. 办公应用

4.1 办公助手

  • PPT助手:PPT制作助手,该应用能够接收关于课程的关键信息和特定要求,根据要求快速完成PPT大纲及内容的生成,并生成PPT文件。
  • 图片视频助手: 文生文、文生图、文生视频,图片处理,帮助教师方便处理图片与视频。
  • PDF一键摘要。

初步分析

1. 行政应用

  • 会议纪要: 记录会议内容和决议的重要文档,‌帮助参会人员回顾会议内容,‌明确工作任务和责任。‌
  • 请假申请:‌用于向上级领导请假并说明请假事由和请假时间。‌
  • 报销申请:‌向财务部门申请报销各类费用的文档。‌
  • 文件传真:‌快速传递文件和信息的沟通工具。‌
  • 安全管理制度:‌包括学校行政方面安全管理制度、‌学校消防安全管理制度、‌学校周边环境安全治理制度等,‌确保校园安全。‌
  • :‌负责学籍信息收集、‌汇总、‌校验、‌上报等工作,‌应用学籍系统开展日常学籍管理工作,‌确保学生学籍信息的真实、‌准确、‌完整。‌

2. 科研应用

  • 论文资料收集:帮助搜集与论文相关的文献与资料。(目前没有很好的模型可以做这类功能,需要做多阶段工作)
  • 论文辅助阅读:论文辅助助手可以快速帮助完成读取分析。运用文档读取插件,可以上传文档分析或总结文章内容,帮助阅读文章并提取知识精华和关键点。
  • 论文写作:论文写作助手可以根据要求帮助快速完成论文写作。输入论文主题,即可生成论文大纲,根据生成的大纲,逐步生成每一章节的论文内容。(可以做,需要做好交互)

3. 教学应用

  • 智能辅导与个性化学习

    • 智能答疑系统 大语言模型即可
    • 个性化学习平台:基于AI的学习平台能够根据学生的学习进度、知识掌握情况和学习习惯定制个性化学习计划,提供个性化的练习题和学习资源。(学生进度,知识掌握情况,学习习惯这些数据从哪里来?)
    • 自适应学习系统:通过分析学生的学习数据,实时调整学习内容和难度,以适应每个学生的学习节奏和需求。(学生的学习数据从哪里来?)
  • AI辅助教学

    • 教学资源推荐:根据教学内容和目标,AI能够自动为教师推荐相关的教学资源、课程素材和教学案例。(需要具体教学资源的例子)
    • 备课助手:备课助手可以在备课环节中辅助教师快速生成教学大纲及教案。应用可根据课程主题、重点及要求,收集网络相关资料,整理并生成备课所需的内容。(直接生成 VS. 收集网络相关资料? 后者代价更大,比如利用perplexity技术(比一般大模型的 key 贵 10 倍))
    • 智能批改作业
    • 课堂管理:智能课堂管理系统可以帮助教师实时监控课堂情况,记录学生出勤、表现,进行课堂互动评估等。(这个看起来不是需要算法做的事)
  • 智能评估与分析

    • 学习数据分析:通过收集和分析学生的学习数据,AI能够生成详细的学习报告,帮助教师了解学生的学习情况和存在的问题,进而调整教学策略。(缺原始数据)
    • 智能测评系统:基于大数据和AI技术,系统能够设计和实施各类学科测评,并对测评结果进行智能分析,提供详细的反馈和改进建议。(没有理解,需要进一步解释)
  • 语言学习与翻译

    • 智能翻译工具(文档,语音)
    • 语音识别与评分:通过语音识别技术,AI能够对学生的发音、语调进行分析和评分,提供改进建议。(这个比较大,可以做,但是需要比较长的时间)
  • 虚拟现实与增强现实

    • 虚拟现实(VR)教学:通过虚拟现实技术,学生可以身临其境地参与到历史事件、科学实验等各种虚拟环境中,增加学习的趣味性和互动性。
    • 增强现实(AR)教材:利用增强现实技术,教科书上的图片可以变成动态的3D模型,帮助学生更直观地理解复杂的概念和内容。
  • 机器人助教

    • 教育机器人:一些先进的教育机器人可以在课堂中扮演助教角色,进行知识讲解、互动问答,甚至帮助老师进行课堂管理。(可以做,但是这里需求不明确)
    • 陪伴型机器人:这些机器人在课堂之外可以陪伴学生学习,进行一些简单的知识问答和互动,激发学生的学习兴趣。(和之前貌似相似)
  • 心理健康与行为分析

    • 智能心理辅导:AI系统能够通过分析学生的行为数据、情绪表达等,帮助识别学生的心理问题,提供心理健康建议和辅助性服务。(可以做,但是这里需求不明确)
    • 行为分析与干预:通过分析学生在课堂中的表现和行为轨迹,AI能够帮助教师识别和管理学生的行为问题,提供个性化的辅导和干预策略。(如何交互?)
  • 教育资源管理

    • 智能排课系统:利用AI技术,能够根据学生和教师的时间表、课程需求,自动生成最优的课程安排方案。(这种不用 AI 最好,更精确,用算法实现)
    • 资源调度与优化:AI系统可以帮助学校优化图书馆、计算机房、多媒体教室等资源的使用,提高资源利用效率。(这种不用 AI 最好,更精确,用算法实现)
  • 智能翻译, 输入待翻译内容,以及需要翻译的语言,输出翻译内容

  • 试题生成: 通过输入知识点,学生年级,题目数量,输出: 卷子,答案,需要去看如何生成电子版供下载

  • 绘图助手:绘图助手可以帮助教师快速生成教学用图、PPT配图等,协助在课堂上对知识内容进行多元化表达。使用自然语言输入画面描述,快速生成图片。

  • 学生评价助手: 通过 prompt 可以调试出合适的,输入:学生不足,学生优点,字数,学生姓名?

4. 办公应用

  • PPT助手:PPT制作助手,该应用能够接收关于课程的关键信息和特定要求,根据要求快速完成PPT大纲及内容的生成,并生成PPT文件。 (需要先提供一批 PPT 模板)
  • 图片视频助手: 文生文、文生图、文生视频,图片处理,帮助教师方便处理图片与视频。
  • PDF一键摘要。
AI大模型AI助教阅读需 15 分钟

[toc]

前言

本系列文章是针对计算机经典书籍《Git 权威指南》的精简版学习笔记,方便大家快速了解内容以及速记,欢迎订阅

上一篇文章,我们学习了创建版本库的几个命令,不熟悉的同学可以参考 Git初始化

  • git log --stat
  • 可以看到每次提交的文件变更统计

5.1 修改不能直接提交吗

  • echo "Nice to meet you" >> welcome.txt
  • git diff
  • 可以看到修改后的文件与本库(与本地比较的不是版本库中的文件,而是一个中间状态的文件)中的文件的差异
  • 工作区与提交任务中相比的差异

diff --git a/welcome.txt b/welcome.txt

index 18832d3..9c2a787 100644

--- a/welcome.txt

+++ b/welcome.txt

@@ -1 +1,2 @@

Hello.

+Nice to meet you

  • 如果此时认为文件修改后可以直接提交,那就错了哦,
  • 尝试运行命令:git commit -m "Append a nice line."
  • 发现会运行不成功
  • 提交日志里面没有新的提交记录出现
  • 执行 git diff 可以看到和之前一样的结果,说明没有提交成功
  • git status查看文件状态,可以看到文件处于修改状态,
  • 精简模式 git status -s

➜ git commit -m "Append a nice line."

On branch master

Changes not staged for commit:

modified: welcome.txt

no changes added to commit

  • 所以如果想提交,需要利用 git add命令
  • git add welcome.txt
  • git diff HEAD
  • 工作区与HEAD相比
  • git diff --stagedgit diff --cached
  • 提交暂存区与版本库中文件的差异
  • git status -s
  • M位于第一列的含义
  • M welcome.txt
  • 版本库中的文件与处于中间状态--提交任务(提交暂存区,stage)中的文件相比有改动
  • M位于第二列的含义
  • 工作区当前的文件与处于中间状态--提交任务(提交暂存区,stage)中的文件相比有改动
  • M welcome.txt
  • 如果此时继续修改welcome.txt 文件
  • echo "Bye-Bye." >> welcome.txt
  • git status -s
  • MM welcome.txt
  • 不但版本库中最新提交的文件与处于中间状态--提交任务(提交暂存区,stage)中的文件相比有改动,而且工作区当前的文件处于中间状态--提交任务(提交暂存区,stage)中的文件相比也有改动
  • 现在再来提交
  • git commit -m "which version checked in?"
  • 如何证明提交成功呢
  • git log --pretty=oneline
  • git status -s
  • git diff

5.2 理解Git暂存区(stage)

  • git status 原理
  • 先依据.git/index文件中记录的时间戳,长度等信息判断工作区文件是否改变
  • 如果工作区文件的时间戳改变了,说明文件的内容可能改变了,需要打开文件,读取文件内容,与源文件做比较,
  • 如果文件内容没有改变,则将该文件新的时间戳记录到.git/index文件中
  • 使用时间戳,文件长度等信息进行比较要比通过文件内容比较要快得多
  • .git/index
  • 实际是一个包含文件索引的目录树,像一个虚拟的工作区
  • 记录了文件名和文件的状态信息(时间戳和文件长度,文件的内容没有存储在其中,而是保存在Git对象库.git/objects目录中

img

  • HEAD实际是指向master分支的一个 “游标”,所以图示的命令中出现HEAD的地方可以用master来替换
  • 图中的objects标识的区域为Git的对象库,实际位于 .git/objects 目录下,这一点会在后面的章节中重点介绍
  • 当对工作区修改(或新增)的文件执行git add命令时,暂存区的目录树将会被更新,同时工作区修改(或新增)的文件内容会被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中
  • 当执行提交操作(git commit)时,暂存区的目录树会写到版本库(对象库)中,master分支会做相应的更新,即master最新指向的目录树就是提交时原暂存区的目录树
  • 当执行git reset HEAD 命令时,暂存区的目录树会被重写,会被master指向的目录树所替换,但是工作区不受影响
  • 当执行git rm --cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变
  • 但执行git checkout ., 或git checkout -- <file> 命令时,会用暂存区全部的文件或制定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动
  • 但执行git checkout HEAD . 或git checkout HEAD <file> 命令时,会用HEAD指向的master分支中的全部或者部分文件替换暂存区和工作区中的文件,这个命令也是极具危险性的,因为不但会清除工作区中的未提交的改动,也会清除暂存区中未提交的改动

5.3 Git Diff魔法

1. 工作区,暂存区和版本库的目录树浏览

➜ git ls-tree -l HEAD

100644 blob 7e12803b85898fd0ae42d0a793c3eaf9f0cdd66e 28 test.ini

100644 blob 9c2a787a930a7b547abdf71e47ab1a67de890832 24 welcome.txt

  • -l 参数可以显示文件的大小
  • 第一个字段是文件的属性(rw-r--r--)
  • 第二个字段说明是Git对象库中的一个blob对象(文件),
  • 第三个字段则是该文件在对象库中对应的ID--一个40位的SHA1哈希值格式的ID
  • 第四个字段是文件大小
  • 第五个字段是文件名
  • 清除当前工作区中没有加入版本库的文件和目录(非跟踪文件和目录)
  • git clean -fd
  • 用暂存区内容刷新工作区
  • git checkout .
2. Git diff 魔法

img

  • 工作区和暂存区比较
  • git diff
  • 暂存区和HEAD比较
  • git diff --cached
  • 工作区和HEAD比较
  • git diff HEAD

5.4 不要使用git commit -a

  • 好处
  • 减少用git add 命令标识变更文件的步骤
  • 坏处
  • 丢掉Git暂存区带给用户的最大好处:对提交内容进行控制的能力
5.5 搁置问题,暂存状态
  • git stash
  • 保存当前共奏进度
Git阅读需 6 分钟

[toc]

前言

本系列文章是针对计算机经典书籍《Git 权威指南》的精简版学习笔记,方便大家快速了解内容以及速记,欢迎订阅

4.1 创建版本库及第一次提交

  1. 首先查看自己的git版本
  • git --version
  • 比如我的是 git version 2.24.3 (Apple Git-128)
  1. 建立新工作目录
  • 如果git版本是1.6.5+
  • git init demo
  • 否则就一步一步来
  • mkdir demo
  • cd demo
  • git init
  1. 查看隐藏的git目录
  • ls -aF
  • 会显示 ./ ../ .git/
  • 其中 .git 就是Git版本库(又叫仓库,repository)
  • 版本库所在目录称为工作区,比如我的 ~/coding/git/demo
  1. 为工作区加内容
  • echo "Hello." > welcome.txt
  • 需要运行命令 git add welcome.txt将新建立的文件添加到版本库
  • 提交:git commit -m "initialized."
  • -m 为提交说明
  • [master (root-commit) 1a557fb] initialized. 从这可以看出此次提交在名为master分支上,且是该分支的第一个提交(root-commit),提交ID为1a557fb
  • 1 file changed, 1 insertion(+)可以看出此次提交修改了一个文件,包含一行的插入
  • create mode 100644 welcome.txt 可以看出此次提交创建了一个新文件

4.2 思考:为什么工作区根目录下有一个.git目录

  • Git及其他分布式版本控制系统(如Mercurial/Hg, Bazaar)的一个共同特点是版本库位于工作区的根目录下
  • 传统的集中式版本控制系统需要建立版本库和工作区的对应
  • Git的设计是的所有的版本控制操作都在本地即可完成
  • Git提供了一条命令用来搜索工作区的文件内容
  • git grep "Hell"
  • 结果是 welcome.txt:Hello.
  • 如果在工作区的子目录中执行Git命令
  • 会在工作区目录中依此向上递归查找git目录,找到的.git目录就是工作区对应的版本库,.git所在的目录就是工作区的根目录,文件.git/index记录了工作区文件的状态(实际上是暂存区的状态)
  • 在非工作区执行git命令时会因为找不到.git目录而报错
  • 如果想知道工作区的根目录的位置
  • 先创建多级目录并进入
  • mkdir -p a/b/c
  • cd a/b/c
  • 当前目录:~/coding/git/demo/a/b/c
  • 显示版本库.git目录所在的位置
  • git rev-parse --git-dir
  • /Users/xujie/coding/git/demo/.git
  • 显示工作区根目录
  • git rev-parse --show-toplevel
  • /Users/xujie/coding/git/demo
  • 显示工作区根目录的相对目录
  • git rev-parse --show-prefix
  • a/b/c/
  • 显示从当前目录后退到工作区的根的深度
  • git rev-parse --show-cdup
  • ../../../

4.3 git config命令的各参数有何区别

  • 使用不同参数的git config命令时机操作了不同的文件
  • git config -e
  • 实际上操作 ./demo/.git/config (版本库级别,优先级最高)
  • git config -e --global
  • 实际上操作: ~/.gitconfig (用户全局配置)
  • git config -e --system
  • 实际上操作 /etc/gitconfig (系统级别)
  • git配置文件采用的是INI 文件格式
  • cat .git/config

[core]

repositoryformatversion = 0

filemode = true

bare = false

logallrefupdates = true

ignorecase = true

precomposeunicode = true

  • 读取配置文件的属性
  • git config <section>.<key>
  • git config core.bare
  • false
  • 更改或者设置INI文件中某个属性的值
  • git config a.b something
  • git config x.y.z something

$ cat .git/config

[core]

repositoryformatversion = 0

filemode = false

bare = false

logallrefupdates = true

symlinks = false

ignorecase = true

[a]

b = something

[x "y"]

z = something

  • 操作任何其他的INI文件
  • GIT_CONFIG=test.ini git config a.b.c.d "hello, world"

$ cat test.ini

[a "b.c"]

d = hello, world

  • 从配置文件test.ini中读取配置
  • GIT_CONFIG=test.ini git config a.b.c.d
  • hello, world

4.4 思考:是谁完成的提交

  • 可以通过执行下面的命令删除user.name 和 user.email的配置
  • git config --unset --global user.name
  • git config --unset --global user.email
  • 然后提交
  • git commit --allow-empty -m "who does commit?"

[master df2b623] who does commit?

Committer: xujie <xujie@xujies-MacBook-Pro.local>

Your name and email address were configured automatically based

on your username and hostname. Please check that they are accurate.

You can suppress this message by setting them explicitly:

git config --global user.name "Your Name"

git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

git commit --amend --reset-author

1 file changed, 2 insertions(+)

create mode 100644 test.ini

  • git log --pretty=fuller

commit df2b62367ca80056d248113aed8f3dd4d10dcdca (HEAD -> master)

Author: xujie <xujie@xujies-MacBook-Pro.local>

AuthorDate: Wed Sep 28 22:37:49 2022 +0800

Commit: xujie <xujie@xujies-MacBook-Pro.local>

CommitDate: Wed Sep 28 22:37:49 2022 +0800

who does commit?

commit 1a557fb84b2ed006bca7395729b1efb71baf96f1

Author: jiexu <admin@example.com>

AuthorDate: Wed Sep 28 21:39:06 2022 +0800

Commit: jiexu <admin@example.com>

CommitDate: Wed Sep 28 21:39:06 2022 +0800

initialized.

  • 重新配置提交者信息
  • git config --global user.name "jiexu"
  • git config --global user.email jiexu@example.com
  • 重新提交修改
  • git commit --amend --allow-empty --reset-author

4.5 思考:随意设置提交者姓名,是否不太安全

  • 这是分布式版本控制系统的特性使然,每个人都是自己的版本库的主人,很难也没有必要进行身份认证,所以无法使用经过认证的用户名作为提交的用户名

备份本章的工作

  • 备份内容
  • git clone demo demo-step-1
Git阅读需 5 分钟

数据库篇

  • 查看已有数据库
  • \l

recipes=# \l

List of databases

Name | Owner | Encoding | Collate | Ctype | Access privileges

-----------+----------+----------+------------+------------+-----------------------

postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |

recipes | postgres | UTF8 | en_US.utf8 | en_US.utf8 |

template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +

| | | | | postgres=CTc/postgres

template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +

| | | | | postgres=CTc/postgres

(4 rows)

  • 选择数据库
  • \c + 数据库名称,例:\c recipes

表相关命令

  • 查看所有表
  • \dt
  • \d
  • select * from pg_tables;这个命令会列出所有的,包含postgresql自己的
  • select tablename from pg_tables where schemaname='public'

List of relations

Schema | Name | Type | Owner

--------+-------+-------+----------

public | image | table | postgres

(1 row)

  • 查看表结构
  • \d + 表名,例如:\d image
  • SQL 方式

SELECT a.attnum,a.attname AS field,t.typname AS type,a.attlen AS length,a.atttypmod AS lengthvar,a.attnotnull AS notnull

FROM pg_class c,pg_attribute a,pg_type t

WHERE c.relname = 'cms_qq' and a.attnum > 0 and a.attrelid = c.oid and a.atttypid = t.oid

ORDER BY a.attnum;


Table "public.image"

Column | Type | Collation | Nullable | Default

--------------+-----------------------------+-----------+----------+---------

orignal_path | character varying(1000) | | not null |

image_path | character varying(1000) | | not null |

dir | character varying(100) | | not null |

has_niaowo | boolean | | |

has_detected | boolean | | not null | false

created_at | timestamp without time zone | | not null | now()

deleted | boolean | | not null | false

version | integer | | not null | 0

PostgreSQL阅读需 2 分钟

* git fetch --tags --progres
* git rev-parse
* git config core.sparsecheckout
* git checkout -f
Git阅读需 1 分钟

说出三种线程间通信的方式

  • Thread + Handler
  • 广播
  • AsyncTask

说出三种进程间通信的方式

  • AIDL
  • 消息队列
  • 管道
操作系统阅读需 1 分钟

Linux入门概述

Linux 内核最初是由芬兰人

VM安装相关

Linux目录结构

系统管理操作

远程登录

用户和用户组管理命令

基本常用命令

VI/VIM编辑器

rpm

shell编程

Linux阅读需 1 分钟

初识MPI

MPI介绍

  • MPI,全称Message Passing Interface(消息传递接口),是业界定义的一种消息传递标准,用于编写并行计算的程序,广泛应用于高性能计算领域。

环境准备

  • 安装过程(ubuntu 18.04)
  • sudo apt-get update
  • sudo apt-get install -y build-essential
  • gcc -v

MPICH

  • MPICH是MPI标准的一种重要的实现,可以免费从网上下载。MPICH的开发与MPI规范的制订是同步进行的,因此MPICH最能反映MPI的变化和发展。
  • sudo apt-get install -y mpich
  • mpicc -v

第一个MPI程序

  • sudo apt-get install -y vim
  • vim mpi.c

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{

MPI_Init(&argc, &argv);

printf("Hello World!\n");

MPI_Finalize();

return 0;

}

  • mpicc mpi.c -o mpi.o
  • mpirun -np 8 ./mpi.o
  • MPI程序和普通的C程序的区别在于有一个开始的函数和结束的函数来标识MPI部分,再在这个部分进行你想要进行的操作
  • int MPI_Init(int *argc, char **argv)
  • 通过MPI_Init函数进入MPI环境并完成所有的初始化工作,标志并行代码的开始。
  • int MPI_Finalize(void)
  • 通过MPI_Finalize函数从MPI环境中退出,标志并行代码的结束,如果不是MPI程序最后一条可执行语句,则运行结果不可知。

MPI学习

获取进程数量

  • 在MPI编程中,我们常常需要获取指定通信域的进程个数,以确定程序的规模。
  • 一组可以相互发送消息的进程集合叫做通信子,通常由MPI_Init()在用户启动程序时,定义由用户启动的所有进程所组成的通信子,缺省值为 MPI_COMM_WORLD。这个参数是MPI通信操作函数中必不可少的参数,用于限定参加通信的进程的范围。
  • int MPI_Comm_size(MPI_Comm comm, int *rank)
  • 获取指定通信域的进程个数。
  • 第一个参数是通信子,第二个参数返回进程的个数。

#include <stdio.h>

#include <mpi.h>

int main(int argc, char **argv)

{

int numprocs;

MPI_Init(&argc, &argv);

//your code here

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

//end of your code

printf("Hello World! The number of processes is %d\n",numprocs);

MPI_Finalize();

return 0;

}

获取进程id

  • 常常需要输出当前进程的id,以此来判断具体哪个进程完成了对应的任务。
  • int MPI_Comm_rank(MPI_Comm comm, int *rank)
  • 获得当前进程在指定通信域中的编号,将自身与其他程序区分。
  • 第一个参数是通信子,第二个参数返回进程的编号。

#include <stdio.h>

#include <mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

//your code here

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

//end of your code

printf("Hello World!I'm rank %d of %d\n", myid, numprocs);

MPI_Finalize();

return 0;

}

获取处理器名

  • 在实际处理中我们可能需要将进程迁移至不同的处理器,而MPI提供了获取处理器名的函数以简单地允许这种行为。
  • 注意在MPI中不需要定义这种迁移。
  • int MPI_Get_processor_name ( char *name, int *resultlen)
  • char *name : 实际节点的唯一说明字;
  • int *resultlen:在name中返回结果的长度;
  • 返回调用时调用所在的处理器名。

#include <stdio.h>

#include <mpi.h>

int main(int argc, char **argv)

{

int len;

char name[MPI_MAX_PROCESSOR_NAME];

MPI_Init(&argc, &argv);

//your code here

MPI_Get_processor_name (name, &len);

//end of your code

printf("Hello, world. I am %s.\n", name);

MPI_Finalize();

return 0;

}

运行时间

  • 在MPI编程我们可以使用MPI_Wtime函数在并行代码中计算运行时间,用MPI_Wtick来查看精度。
  • double MPI_Wtime(void)
  • MPI_WTIME返回一个用浮点数表示的秒数, 它表示从过去某一时刻到调用时刻所经历的时间。
  • double MPI_Wtick(void)
  • MPI_WTICK返回MPI_WTIME的精度,单位是秒,可以认为是一个时钟滴答所占用的时间。

#include<stdio.h>

#include<mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

double start, finish;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

//your code here

start = MPI_Wtime();

printf("The precision is: %f\n", MPI_Wtick());

finish = MPI_Wtime();

//your code here

printf("Hello World!I'm rank %d of %d, running %f seconds.\n", myid, numprocs, finish-start);

MPI_Finalize();

return 0;

}

同步

  • 在实际工作中,我们常常会因为许多原因需要进行同步操作。例如,希望保证所有进程中并行代码在某个地方同时开始运行,或者在某个函数调用结束之前不能返回。
  • int MPI_Barrier(MPI_Comm comm)
  • 阻止调用直到communicator中所有进程已经完成调用,
  • 就是说,任意一次进程的调用只能在所有communicator中的成员已经开始调用之后进行。

#include<stdio.h>

#include<mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

double start, finish;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

//your code here

MPI_Barrier(MPI_COMM_WORLD);

//end of your code

start = MPI_Wtime();

printf("The precision is: %f\n", MPI_Wtick());

finish = MPI_Wtime();

printf("Hello World!I'm rank %d of %d, running %f seconds.\n", myid, numprocs, finish-start);

MPI_Finalize();

return 0;

}

消息传递

  • 在并行编程中,消息传递占了很大的比重。良好的消息传递是正常完成进程/节点之间操作的基本条件。在这里先介绍的最基本发送/接收函数。
  • 最基本的发送/接收函数都是以缓冲区作为端点,通过参数配置来完成指定操作。
  • `int MPI_Send(void* msg_buf_p, int msg_size, MPI_Datatype msg_type, int dest, int tag, MPI_Comm communicator)

`

  • 发送缓冲区中的信息到目标进程。

void* msg_buf_p : 发送缓冲区的起始地址;

int buf_size : 缓冲区大小;

MPI_Datatype msg_type : 发送信息的数据类型;

int dest :目标进程的id值;

int tag : 消息标签;

MPI_Comm communicator : 通信子;

  • `int MPI_Recv(void* msg_buf_p, int buf_size, MPI_Datatype msg_type, int source, int tag, MPI_Comm communicator, MPI_Status *status_p)

`

  • 发送缓冲区中的信息到目标进程。

void* msg_buf_p : 缓冲区的起始地址;

int buf_size : 缓冲区大小;

MPI_Datatype msg_type : 发送信息的数据类型;

int dest :目标进程的id值;

int tag : 消息标签;

MPI_Comm communicator : 通信子;

MPI_Status *status_p : status_p对象,包含实际接收到的消息的有关信息

  • 实验说明:
  • 在这里我们把id为0的进程当作根进程,然后在除此之外的进程中使用函数MPI_Send发送一句"hello world!"到根进程中,然后在根进程中把这些信息打印出来。

#include <stdio.h>

#include <mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs, source;

MPI_Status status;

char message[100];

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

if(myid != 0) {

strcpy(message, "hello world!");

//your code here

MPI_Send(message, strlen(message)+1, MPI_CHAR, 0, 99, MPI_COMM_WORLD);

//end of your code

}

else { //myid == 0

for(source=1; source<numprocs; source++) {

//your code here

MPI_Recv(message, 100, MPI_CHAR, source, 99, MPI_COMM_WORLD, &status);

//end of your code

printf("%s\n", message);

}

}

MPI_Finalize();

return 0;

}

地址偏移量

  • 在通信操作中,我们常常需要对地址进行传递或操作,例如传送/接收缓冲区。
  • 而一个位置在内存中的地址可以通过MPI_ADDRESS函数获得。
  • int MPI_Address(void* location, MPI_Aint *address)
  • void* location : 调用者的内存位置;
  • MPI_Aint *address:位置的对应地址;
  • 实验说明:
  • 给出三个临时变量a, b, c, 分别求出a与b、a与c之间的地址偏移量。
  • 输出结果:
  • 由于这里采用的变量类型为int,所以如果变量地址是连续的话应该是:

The distance between a and b is 4

The distance between a and c is 8


#include<stdio.h>

#include<mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

MPI_Aint address1, address2, address3;

int a, b, c, dist1, dist2;

a = 1;

b = 2;

c = 3;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

// your code here

MPI_Address(&a, &address1);

MPI_Address(&b, &address2);

MPI_Address(&c, &address3);

// end of your code

dist1 = address2 - address1 ;

dist2 = address3 - address1 ;

if(myid == 0) {

printf("The distance between a and b is %d\n", dist1);

printf("The distance between a and c is %d\n", dist2);

}

MPI_Finalize();

return 0;

}

数据的打包(pack)

  • 有时候我们希望将不连续的数据或是不相同的数据类型的数据一起发送到其他进程,而不是效率很低地逐个发送。
  • 一个解决这个问题的方案是将数据封装成包,再将数据包放到一个连续的缓冲区,发送到接收缓冲区后再提取出来尽心解包。
  • 值得注意的是,打包/解包函数有时候还会用来代替系统缓存策略。此外,对于在MPI顶层进一步开发附加的通信库会起到辅助的作用。

int MPI_Pack(void* inbuf, int incount, MPI_datatype datatype, void *outbuf, int outcount, int *position, MPI_Comm comm)

void* inbuf : 输入缓冲区地址;

int incount :输入数据项数目;

MPI_datatype datatype :数据项的类型;

void *outbuf :输出缓冲区地址;

int outcount :输出缓冲区大小;

int *position :缓冲区当前位置;

MPI_Comm comm :通信子;

  • 实验说明:
  • 在源进程中打包发送一个数据包到进程1,进程1解包并打印出数据。
  • 输出结果:

The number is 1 and 2


#include <stdio.h>

#include <mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs, source;

MPI_Status status;

int i, j, position;

int k[2];

int buf[1000];

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

i = 1;

j = 2;

if(myid == 0) {

position = 0 ;

// your code here

MPI_Pack(&i, 1, MPI_INT, buf, 1000, &position, MPI_COMM_WORLD);

MPI_Pack(&j, 1, MPI_INT, buf, 1000, &position, MPI_COMM_WORLD);

// end of your code

MPI_Send(buf, position, MPI_PACKED, 1, 99, MPI_COMM_WORLD);

}

else if (myid == 1){

MPI_Recv(k, 2, MPI_INT, 0, 99, MPI_COMM_WORLD, &status);

position = 0 ;

MPI_Unpack(k, 2, &position, &i, 1, MPI_INT, MPI_COMM_WORLD);

MPI_Unpack(k, 2, &position, &j, 1, MPI_INT, MPI_COMM_WORLD);

printf("The number is %d and %d", i, j);

}

MPI_Finalize();

return 0;

}

数据的解包(unpack)

  • 解包是对应于打包的MPI操作。
  • 需要特别注意的是:
  • MPI_RECV和MPI_UNPACK的区别:
  • 在MPI_RECV中, count参数指明的是可以接收的最大项数. 实际接收的项数是由接收的消息的长度来决定的.
  • 在MPI_UNPACK中, count参数指明实际打包的项数; 相应消息的"size"是position的增加值.
  • 这种改动的原因是"输入消息的大小" 直到用户决定如何解包之前是不能预先确定的;
  • 从解包的项数来确定"消息大小"也是很困难的。

int MPI_Unpack(void* inbuf, int insize, int *position, void *outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm)

void* inbuf : 输入缓冲区地址;

int insize :输入数据项数目;

MPI_datatype datatype :数据项的类型;

void *outbuf :输出缓冲区地址;

int outcount :输出缓冲区大小;

int *position :缓冲区当前位置;

MPI_Comm comm :通信子;

规约(reduce)

  • 在现实生活中,我们常常需要对于数据做同一种操作,并将结果返回到指定的进程中,这个过程称为集合通信。例如,将数据分散到各个进程中,先在各个进程内进行求和,再在全局完成求和-平均这个操作,这个过程是一个规约的过程。
  • 一般来说,集合通信包括通信、同步和计算三个功能。不过,目前我们暂时不需要关注整个过程,而是先使用一个规约函数去体验一下集合通信。
  • int MPI_Reduce(void * input_data_p, void * output_data_p, int count, MPI_Datatype datatype, MPI_Op operator, int dest_process, MPI_Comm comm)
  • 规约函数,所有进程将待处理数据通过输入的操作子operator计算为最终结果并将它存入目标进程中。

void * input_data_p : 每个进程的待处理数据存放在input_data_p中;

void * output_data_p : 存放最终结果的目标进程的地址;

int count : 缓冲区中的数据个数;

MPI_Datatype datatype : 数据项的类型;

MPI_Op operator : 操作子,例如加减;

int dest_process : 目标进程的编号;

  • 实验说明:
  • 使用函数MPI_Reduce来完成加法规约到根进程的操作,并在根进程打印出总和和平均值。
  • 输出结果:
  • 由于这里是测试用例,所以每个进程的数值都是取3.0。所以,输出结果应该是总和等于进程数乘以3,平均值应该是3。

#include <stdio.h>

#include <mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

double local_num = 3.0;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

double global_num;

//your code here

MPI_Reduce(&local_num, &global_num, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

//end of your code

if(myid == 0) {

printf("Total sum = %f, avg = %f\n", global_num, global_num / numprocs);

}

MPI_Finalize();

return 0;

}

广播(broadcast)

  • 在一个集合通信中,如果属于一个进程的数据被发送到通信子中的所有进程,这样的集合通信叫做广播。
  • int MPI_Bcast(void* buffer, int count, MPI_Datatype datatype, int source, MPI_Comm comm)
  • 广播函数,从一个id值为source的进程将一条消息广播发送到通信子内的所有进程,包括它本身在内。

void*  buffer   缓冲区的起始地址;

int   count    缓冲区中的数据个数;

MPI_Datatype datatype   缓冲区中的数据类型;

int   source    发送信息的进程id;

MPI_Comm comm    通信子;

  • 实验说明:
  • 使用函数MPI_Bcast在根进程中发送一个数组到其他进程,并在其他进程中打印出来。
  • 输出结果:
  • 输出应该是这样的格式:

In process 1, arr[0]=1 arr[1]=2 arr[2]=3 arr[3]=4 arr[4]=5

In process 3, arr[0]=1 arr[1]=2 arr[2]=3 arr[3]=4 arr[4]=5

...

In process n, arr[0]=1 arr[1]=2 arr[2]=3 arr[3]=4 arr[4]=5


#include<stdio.h>

#include<mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

int source = 0;

int array[5]={1,2,3,4,5};

int i;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

if(myid == source) {

for(i = 1; i <= 5; i++)

array[i] = i;

}

//your code here

MPI_Bcast(array, 5, MPI_INT, source, MPI_COMM_WORLD);

//end of your code

if(myid != source) {

printf("In process %d, ", myid);

for(i = 0; i < 5; i++)

printf("arr[%d]=%d\t", i, array[i]);

printf("\n");

}

MPI_Finalize();

return 0;

}

收集(gather)

  • 同样,有时候我们希望在一个进程中从所有进程获取信息,例如将所有进程中的一个数组都收集到根进程中作进一步的处理,这样的集合通信我们叫做收集。
  • `int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendtype,

void* recvbuf, int recvcount, MPI_Datatype recvtype,

int root, MPI_Comm comm)`

  • 收集函数,根进程(目标进程)从所有进程(包括它自己)收集发送缓冲区的数据,根进程根据发送这些数据的进程id将它们依次存放到自已的缓冲区中.

void* sendbuf 发送缓冲区的起始地址

int sendcount 发送缓冲区的数据个数

MPI_Datatype sendtype 发送缓冲区的数据类型

void* recvbuf 接收缓冲区的起始地址

int recvcount 待接收的元素个数

MPI_Datatype recvtype 接收的数据类型

int root 接收进程id

MPI_Comm comm 通信子

  • 实验说明:
  • 使用函数MPI_Gather在根进程中从所有进程接收一个数组,并在根进程中打印出来。
  • 输出结果:输出应该是这样的格式:

Now is process 1's data: arr[0]=1 arr[1]=2 arr[2]=3 arr[3]=4 arr[4]=5

Now is process 4's data: arr[0]=1 arr[1]=2 arr[2]=3 arr[3]=4 arr[4]=5

Now is process 2's data: arr[0]=1 arr[1]=2 arr[2]=3 arr[3]=4 arr[4]=5

...

Now is process n's data: arr[0]=1 arr[1]=2 arr[2]=3 arr[3]=4 arr[4]=5

...


#include<stdio.h>

#include<mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

int dest = 0;

int array[5]={1,2,3,4,5};

int *rbuf;

int i,j;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

if(myid == dest) {

rbuf=(int *)malloc(numprocs*5*sizeof(int));

}

//your code here

MPI_Gather(array, 5, MPI_INT, rbuf, 5, MPI_INT, dest, MPI_COMM_WORLD);

//end of your code

if(myid == dest) {

for(i=dest+1;i<numprocs;i++) {

printf("Now is process %d's data: ", i);

for(j=0;j<5;j++) {

printf("array[%d]=%d\t", j, rbuf[i*5+j]);

}

printf("\n");

}

}

MPI_Finalize();

return 0;

}

14. 散发(scatter)

  • 在前面我们学习了收集(gather)操作,那么与之相对应也有一个相反的集合通信操作,即根进程向所有进程发送缓冲区的数据,称为散发。
  • 需要特别说明的是,散发操作和广播操作的区别在于发送到各个进程的信息可以是不同的
  • `int MPI_Scatter(void* sendbuf, int sendcount, MPI_Datatype sendtype,

void* recvbuf, int recvcount, MPI_Datatype recvtype,

int root, MPI_Comm comm)`

  • MPI_SCATTER是MPI_GATHER的逆操作,另外一种解释是根进程通过MPI_Send发送一条消息,这条消息被分成n等份,第i份发送给组中的第i个处理器, 然后每个处理器如上所述接收相应的消息。

void* sendbuf 发送缓冲区的起始地址

int sendcount 发送的数据个数

MPI_Datatype sendtype 发送缓冲区中的数据类型

void* recvbuf 接收缓冲区的起始地址

int recvcount 待接收的元素个数

MPI_Datatype recvtype 接收的数据类型

int root 发送进程id

MPI_Comm comm 通信子

  • 实验说明:
  • 使用函数MPI_Scatter在根进程中向所有进程发送对应数组,并在对应进程中打印出来。
  • 输出结果:输出应该是这样的格式:

Now is process 1: arr[0]=5 arr[1]=6 arr[2]=7 arr[3]=8 arr[4]=9

Now is process 4: arr[0]=20 arr[1]=21 arr[2]=22 arr[3]=23 arr[4]=24

Now is process 2: arr[0]=10 arr[1]=11 arr[2]=12 arr[3]=13 arr[4]=14

...

Now is process n: arr[0]=5n arr[1]=5n+1 arr[2]=5n+2 arr[3]=5n+3 arr[4]=5*n+4

...


#include<stdio.h>

#include<mpi.h>

int main(int argc, char **argv)

{

int myid, numprocs;

int source = 0;

int *sbuf;

int rbuf[5];

int i;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myid);

MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

if(myid == source) {

sbuf=(int *)malloc(numprocs*5*sizeof(int));

for(i=0;i<numprocs*5;i++) {

sbuf[i]=i;

}

}

// your code here

MPI_Scatter(sbuf, 5, MPI_INT, rbuf, 5, MPI_INT, source, MPI_COMM_WORLD);

// end of your code

printf("Now is process %d: ", myid);

for(i=0;i<5;i++) {

printf("array[%d]=%d\t", i, rbuf[i]);

}

printf("\n");

MPI_Finalize();

return 0;

}

15. 组的管理-创建(1)

并发面试阅读需 14 分钟

1. 初级

1.1 初级学习者的定义

初级阶段规划针对的主要人群:

  • 绝大部分刚入学的大学生(高考非高分)
  • 低分飞过四六级的大学生
  • 基础一般但也没太差的人
  • 过去英文还不错,但是放弃太久想捡回来的人
  • 有一定基础,想快速提高使用技能尤其是听说能力的职场人士
  • 勉强能听懂VOA慢速英语,长苏英语完全抓瞎,也不知道怎么学英语的人

初级可能是整个课程里性价比最高的章节:

  • 几乎每天都能觉察到提高
  • 每天学到的东西第二题立刻就能涌出来
  • 尤其适用于太忙没有时间的职场人士

好处:

  • 听懂同事说话
  • 各方面交流头功面试都没问题
  • 几乎免费,而且非常有效果
  • 搞定职场大部分英文口语问题

坚持下去!!!

1.2 初级学习者目标和效果评估

初级希望大家能够达到的学习目标

  • 基本的日常和商业口语用法词汇量(大约达到3000左右)
  • 系统的学完发音,并掌握基本的连读只是和自然语流规律
  • 具备基本的开口交流能力

选择初级的前提:具备了基本的高中英语基础!

1.3 初级学习者学习规划和方法

初级分为三大阶段,一共学完大约需要1到3个月(视水平基础)

  • 正音(1-3周)
  • 日常口语和语流训练(1到2个月)
  • 商业材料听力,商业领域用法,和词汇量积累(1到2个月)

1.3.1 正音

1.3.1.1 材料1《赖世雄 美语音标》

选用教材:《赖世雄 美语音标》不到20元

这本书比较与众不同,全书的精华就在于播讲录音

这本书配有他的全文讲解,详细讲解了所有发音的诀窍,并且用自己的发音反复做例证,带领大家认证学好

这种个人学习的诀窍和体验,对于大部分想提高发音的同学来说,可以说是无价之宝

比其它粗制滥造拼凑出来的发音书好太多了

为什么一定要从音标学起?

因为练听力的最佳方法不是直接就挑选适合自己的材料开始挺,而是先学发音,然后再听

推荐学习方法

第一步:

看书听CD不要暂停,跟着录音大声模仿,从头到尾系统把书学个2-3遍

中间遇到自己觉得比较难的章节和句子,在书里面做笔记

第一步建议在一周内搞定

第二步:

找出重难点的章节,重点出击学习,反复听讲解和模仿,尽可能突破

如果实在突破不了,可以暂时先放着,不影响,因为一开始听力能力较低,肯定不能模仿好所有发音的。

这一步也尽量在一两周内搞定

少即是多,慢即是快

建议至少要在2-3周把书过几遍

然后立刻进入初级阶段的第二个环节大量的实战输入,这样才能达到学习效果的巩固和最大化

注意要点1

本书中的所有音标,都是用KK美式音标标注的

  • 和大家从小学习的国际音标标注法略有不同,因此会有人反映学习起来有些困难
  • 完全忘记自己学过音标,从头开始学,当做一门新的学问来学习

注意要点2

有关KK音标的实用问题

  • 目前只要是稍微正式的词典,都一定会标注英美两种发音
  • 一般都是英音在前,美音在后,无论是牛津朗文还是剑桥,都是如此

注意要点3

发音不可能通过一本书就学好

  • 仅仅通过一本书的学习量,很难把你持续了整整20年的糟糕发音习惯全部都改过来
  • 一本书的含量毕竟有限,不可能把所有发音现象规律都囊括进去,更不能提供足够多的练习让你把发音规律彻底活化
  • 这些练习,我们将在第三阶段提供

注意要点4

学音标就一定要用!绝对不要自我欺骗

  • 有很多人已学习就会患上金鱼症,记忆时间超级短,学的时候跟着赖老师读的很欢唱,很标准,把书抛开,立刻打回原形,而且不是说不知道自己说错了,而是明明知道错了,却懒得改
  • 每天学一点新的规则和舌位,就必须立刻用起来!不管什么场合,谈话,朗读,背单词,都要有意识的去多使用,哪怕再难受,直到彻底成为习惯
1.3.1.2 材料2

Coach Shane's Daily Easy English Expression

  • 是由美国的英语老师coach shane制作的
  • Coach Shane并没有什么显赫的背景,身份和头衔,但他是我在数十年间,遇到过最厉害的老师,教学功力非常深厚,很难找到这么一位如此擅长语音,听力和口语教学的老师
  • 这套材料,一共有1000多个视频,每个视频都很短,也就只有几分钟而已

为什么一定要从音标学起?

  • 想要提高耳朵和大脑对听力的反应速度,训练的关键点在于摸清英文信息语流的规律
  • 把这些规律总结出来,让大脑进行学习
  • 一旦大脑熟悉摸清各类规律,就能大幅提高理解力和理解速度
  • 而英文语流的规律中,分拆到最简化最细小的元素,就是单个的音标了

单单是把音标学好,就能大幅优化你的大脑处理器,学完之后你会发现自己对于英文听力更加敏感,听力能力也突然提高了一大截,没有比这性价比更高的事儿了

英语学习技巧阅读需 6 分钟