关于 2020 到目前的一个总结
2020 年对全人类来说是不平凡的一年,而对我来说也是不同寻常的一年。这一年发生了许多大大小小的事,有些事情身处其中时觉得非常不得了,而经历过后,又觉得也许很快就会忘记,因此想记录一些这一年我都干了些什么事。
2020 年对全人类来说是不平凡的一年,而对我来说也是不同寻常的一年。这一年发生了许多大大小小的事,有些事情身处其中时觉得非常不得了,而经历过后,又觉得也许很快就会忘记,因此想记录一些这一年我都干了些什么事。
由于目前在电脑上运行一个虚拟机已经比较流畅,而虚拟机又有着真机无法比拟的优势,如:
因此我配置了一台 Ubuntu18.0 的虚拟机,并做了以下配置:
其中,关于最后一点。刚开始我采用了桥接网络 + 静态 ip 的方案。但是发现当主机网络环境改变时,ssh 便连接不上了,于是便有了这篇博客。
词法分析:解析源代码文件,输出记号流。 记号即指一个有独立意义的“单词”。空白字符便一般不包含意义,故可以省略。 这些单词一般可分类为:标识符,常数(整数,浮点数),字符常量,字符串, 操作符,界符,关键字。
语法分析:分析记号流,输出程序的逻辑结构,如语法分析树(或 AST 树) 一种语言的语法规则可以被文法产生式完全定义。 文法一般包括表达式的定义,各种语句的定义(if, while, for),变量声明, 函数定义等。
重写了 bad-apple 的代码,利用了多进程的方式进行视频转换。
以下是各个配置转换 bad apple.mp4 的时间
线性执行 | 4 线程 | 1 进程 | 2 进程 | 4 进程 | 8 进程 | 16 进程 | |
---|---|---|---|---|---|---|---|
时间 (秒) | 34.97 | 34.70 | 35.05 | 24.15 | 18.11 | 18.09 | 18 |
其中线程为采用 threading 库,进程则采用 multiprocessing 库
我的电脑配置为:
CPU | intel(R) Core(TM) i5-7200U CPU @ 2.50GHz 2.70GHz |
---|---|
RAM | 8.00 GB |
Windows | Windows10 家庭版 1909 18363.720 |
官方文档说明了 threading 库底层实现时仍只有一个线程,因而只适用于大量 I/O 并发的情况。而我们的图片转换成字符画的过程主要是计算密集型,因此基本没有改善性能。
而采用多进程时,刚好对应我电脑的 4 线程(2 核,采用超线程技术可以有 4 个线程,其实这里进程线程有点晕)时提升最大。
于是便想知道 32 个核时,能提升多少,便想在服务器上跑跑看。以下是配置运行过程。
出人意料的结果:
1 进程 | 4 线程 | 8 进程 | 16 进程 | 32 进程 | |
---|---|---|---|---|---|
时间 (秒) | 51 | 24 | 23.22 | 21.57 | 21.14 |
可能进程多了后,写文件的速度反而成了瓶颈,查看 top 发现各个核的 cpu 利用率都只有 10% 左右,在代码中输出 cvt_frame.qsize() 也发现几乎都是满的。(在自己电脑上大多数都是 0,表明 cvt_frame 供不应求)
从方法 1.1 到 1.3 都不必预编译 dlib 库,而是在使用 dlib 的项目中编译。
方法 1.4 介绍了将 dlib 预编译成静态库然后使用时会遇到的一些问题。
看dlib/example/CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(examples)
# Tell cmake we will need dlib. This command will pull in dlib and compile it
# into your project. Note that you don't need to compile or install dlib. All
# cmake needs is the dlib source code folder and it will take care of everything.
add_subdirectory(./dlib dlib_build)
macro(add_example name)
add_executable(${name} ${name}.cpp)
target_link_libraries(${name} dlib::dlib )
endmacro()
# if an example requires GUI, call this macro to check DLIB_NO_GUI_SUPPORT to include or exclude
macro(add_gui_example name)
if (DLIB_NO_GUI_SUPPORT)
message("No GUI support, so we won't build the ${name} example.")
else()
add_example(${name})
endif()
endmacro()
#
add_gui_example(3d_point_cloud_ex)
命令行执行:
mkdir build
cd build
cmake .. -G "Visual Studio 14 2015 Win64" -T host=x64 #-T host=x64告诉CMake生成64bit的可执行文件。其实安装了最新的VisualStudio后,-G -T都不用指定,默认使用最新的VisualStudio,默认64位。
cmake --build . --config Release
使用 CMake GUI 可以设置一些选项,configure, generate 之后可以使用命令行执行最后一步 (不用打开 VisualStudio)
windows 下还需gdi32, comctl32, user32, winmm, ws2_32, or imm32
库
把 dlib 的父目录添加到 include search path
You should NOT add the dlib folder itself to your compiler's include path. Doing so will cause the build to fail because of name collisions (such as dlib/string.h and string.h from the standard library). Instead you should add the folder that contains the dlib folder to your include search path and then use include statements of the form #include
or include "dlib/queue.h". This will ensure that everything builds correctly.
把 dlib/all/source.cpp 添加到源文件
If you are using Visual Studio you add .cpp files to your application using the solution explorer window. Specifically, right click on Source Files, then select Add -> Existing Item and select the .cpp files you want to add.
dlib 的 CMake 脚本包含 INSTALL target,因此可以像其它 C++ 库一样将 dlib 作为一个静态或动态库安装到系统上。
使用预编译的库时,必须保证项目中使用的所有库都是同一个版本的 VisualStudio 编译出来的。
说明:Mixing Multiple Visual Studio Versions in a Program is Evil
windows 下载预编译版 (只含有 msvc 编译的版本)
CMake 直接使用 find_packages 即可。(需添加环境变量,以便找到 OpenCV 的 config 文件)
官方推荐将代码直接包含到项目中编译(好处是没有 ABI 一致性问题)
CMake 中 add_subdirectory(/path/to/dlib/top/dir) 即可。(甚至可以自动从网上下载)
在opencv.org上提供了源代码以及各个操作系统的预编译版。windows 预编译版为一个 installer 程序,运行后会将各种文件 extract 到安装目录。安装完成后,/path/to/opencv/
包含两个目录——build, source。source 为源代码目录 (和直接下载源代码解压一模一样),build 下包含了许多其它文件。其中:
x64/vcxx/下包含 bin/和 lib/,为预编译的库。vcxx 代表使用 MSVC xx 编译的,运行时需要对应的 runtime 库。
IDE | 编译器 |
---|---|
VS2017 | VC15 |
VS2015 | VC14 |
VS2013 | VC12 |
VS2012 | VC11 |
VS2010 | VC10 |
VS2008 | VC9 |
VS2005 | VC8 |
OpenCVConfig.cmake
文件在使用 CMake 编译项目时可使用 find_package 自动搜索头文件、库文件路径略
菜单栏 project->properities。(或在右侧的 Solution Explorer 下找到一个 project(solution 和 project 的关系)。鼠标右键->Properities)
C/C++/AdditionalIncludeDirectories。编译器从该文件夹下查找头文件。
(p.s. #include "opencv2/opencv.hpp"
和#include "opencv.hpp"
对应不同的设置)
Linker/Input/AdditionalDependencies 添加opencv_world420.lib
Linker/General/AdditionalLibraryDirectories 添加opencv_world420.lib
所在目录。(或直接在 3 中输入绝对路径)
设置环境变量,把opencv_world420.dll
所在目录添加到 Path 变量。(否则运行时报错:无法找到opencv_world420.dll
)。不添加环境变量的方法是直接把opencv_world420.dll
拷贝到 exe 所在目录。
p.s. 貌似opencv_world420.lib
表面上是一个静态链接库,但实际上是一个动态链接库,因而运行时需要opencv_world420.dll
。而第 3 步如若改成添加opencv_world420.dll
,则编译失败。
LNK1107 could also occur if you attempt to pass a module (.dll or .netmodule extension created with /clr:noAssembly or /NOASSEMBLY) to the linker; pass the .obj file instead.
参考:Using OpenCV with gcc and CMake
通过 CMake 编译 OpenCV 程序有几点好处:
OpenCVConfig.cmake
文件,需添加到 Path 环境变量)缺点:
(可以先用 CMake 配置好 include, lib 后,生成 sln 并用 VS 打开)
步骤:
添加opencv/build/
到 Path(OpenCVConfig.cmake
所在目录)。
编写CMakeLists.txt
。示例:
使用 CMake GUI,点击 configure(可以先 File->Delete Cache,删除掉之前的配置)
选择 VS 的编译器。
在中间面板修改一些变量的值。(重新 configure)
Generate,在 build 目录下生成 VS 的 sln 文件,双击打开。
在 ALL_BUILD 上右键 build。
BLAS 为 fortran 接口的库,CBLAS 为 C 语言接口的库
tar zxf blas-3.8.0.tgz
tar zxf cblas.tgz
cd BLAS-3.8.0
make #生成blas_LINUX.a
cp blas_LINUX.a ../CBLAS
cd ../CBLAS
vi Makefile.in
#修改
# BLLIB = ../blas_LINUX.a
make #在lib/下生成cblas_LINUX.a
tar zxf hpl-2.3.tar.gz
cd hpl-2.3
cp setup/Make.Linux_PII_CBLAS ./Make.<arch> #在top-level 文件夹下
vi Make.<arch> #修改
make <arch> #在bin/<arch>/下生成HPL.dat xhpl
ARCH = <arch>
TOPdir = /home/mpiuser/hpl-2.3
MPdir = /path/to/OpenMPI
MPinc = -I$(MPdir)/include
MPlib = $(MPdir)/lib/libmpi.so
LAdir =
LAinc =
LAlib = path/to/cblas_LINUX.a path/to/blas_LINUX.a #顺序不能改变,cblas依赖blas
HPL_OPTS = -DHPL_CALL_CBLAS
CC = mpicc
LINKER = mpif77
计算次数:
HPLinpack benchmark input file
Innovative Computing Laboratory, University of Tennessee
HPL.out output file name (if any)
6 device out (6=stdout,7=stderr,file)
1 # of problems sizes (N)
8192 Ns
1 # of NBs
128 NBs
0 PMAP process mapping (0=Row-,1=Column-major)
3 # of process grids (P x Q)
2 1 4 Ps
2 4 1 Qs
16.0 threshold
3 # of panel fact
0 1 2 PFACTs (0=left, 1=Crout, 2=Right)
2 # of recursive stopping criterium
2 4 NBMINs (>= 1)
2 # of panels in recursion
2 NDIVs
3 # of recursive panel fact.
0 1 2 RFACTs (0=left, 1=Crout, 2=Right)
1 # of broadcast
0 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1 # of lookahead depth
0 DEPTHs (>=0)
2 SWAP (0=bin-exch,1=long,2=mix)
64 swapping threshold
0 L1 in (0=transposed,1=no-transposed) form
0 U in (0=transposed,1=no-transposed) form
1 Equilibration (0=no,1=yes)
8 memory alignment in double (> 0)
今天查了一些关于保研的事, 晚上有点失眠。 我回顾了以往的事, 有初中还有高中。
我回忆起那时自己是怎样的模样, 我感慨有些事不记录也许就真的忘了。 我明白如果不经常眺望一下远方, 而只是低头看着现在, 时间也许眨眼就过去了。
要对短期的未来有所计划, 计划不是一个严格的日程表, 让自己失去自由, 而是明白你最近最想做什么, 你现在想做什么。
我想要: 1 我想要练习口语,为夏令营的英语自我介绍做准备 2 我想要联系一些同学,和他们聊聊未来。必定有所收获。 3 我想有一个爱好,如学会基础的日语。 4 我想在编程能力(数据结构和算法)上有所提高。
我发现列出愿望能让自己更加明确方向。
经过昨晚,和今天早上 8 点醒来趴在床上努力的思考。我终于想起了如何使用数学归纳法证明策梅洛定理。然后经过一上午的努力,我成功使用最大最小值算法实现了井字棋 (Tic-Tak-Toe) 的 AI,然后添加到 wwh 的井字棋代码中。
author: 计科卓越班 袁福焱 20174260
RISC-V 是 21 世纪诞生的一种完全开放的计算机精简指令集,可应用于小到嵌入式系统大到高性能处理器等广泛领域。RISC-V 充分汲取了许多指令集的实践经验,具有非常多的优点。并且它完全开放,采用 BSD 开源协议——全世界任何公司、大学、个人都可以自由免费地使用 RISC-V 指令集构建自己的系统。
本报告第一部分讲述 RISC-V 的几个主要特点与优势,第二部分介绍 RISC-V 的目前已构建建的生态系统。最后一部分,谈论 RISC-V 在推动开源硬件中起到的作用。
以往的指令集为了实现兼容,往往采用增量扩展的方法。即新的处理器不仅要实现新的扩展,还必需要实现过去所有的扩展。如典型的 x86 架构,其中许多指令早已失效,但为了兼容性却必须实现,这导致硬件实现变得越来越复杂。RISC-V 按照功能将指令集分为很多个模块。其中 I 模块为基础整型指令集,这是 RISC-V 要求必须实现的指令集,并且永远不会发生改变。只要实现了该指令集便可以运行完整的基于 RISC-V 的软件。这样,RISC-V 在扩展时便不再会像 x86 那样背上沉重的历史包裹。编译器也可以在保证兼容的基础上,根据已实现的扩展,选择性地生成更高效的代码。
目前主流的指令集有 x86, ARM, MIPS 等。其中 x86 为复杂指令集 (RISC),于 1978 年诞生。而 ARM, MIPS 为精简指令集 (RISC),都是 1986 年诞生的。从计算机体系结构的发展上来看,RISC 由于简洁性,能够更加充分地利用现代微体系结构中的流水线、分支预测、cache 等技术,因此比 CISC 更加高效。因此,诞生于 21 世纪 (2004) 的 RISC-V,必然也是精简指令集。并且,由于有了前面指令的经验,RISC-V 吸收了以往指令集的优点,并回避了以往指令集的一些缺陷。优点如,RISC-V 有 32 个通用寄存器,有专门的 0 寄存器。使用专门的移位指令来处理移位操作。使用 load/store 指令访问内存。跳转指令不使用条件码。缺陷则如,RISC-V 废弃了 MIPS 中的分支延迟槽 (有利于架构和实现的分离),立即数只进行有符号扩展,算数运算不抛出异常 (通过软件判断),更规整的指令格式(源及目的字段位置固定),整数乘除法可选 (简化了基础实现)。
RISC-V 采用 BSD 开源协议,任何人都可以自由免费地使用 RISC-V。其他指令集如 x86 是完全闭源的,只有 intel 和 AMD 等少数公司能够基于 x86 架构生产产品。而 ARM 和 MIPS 都采用授权的方式,通过卖授权的方式盈利,其中 ARM 的授权费则十分昂贵。RISC-V 如今由 RISC-V 基金会维护,任何公司只要愿意每年支付一笔会员费即可成为会员,会员可以参与到 RISC-V 之后标准的制定中。RISC-V 也因此真正成为一个开放的指令集,不会因为任何一个公司的起伏而受到影响。
以下内容引用自开放指令集与开源芯片进展报告-v1p1
2011 年,加州大学伯克利分校发布了开放指令集 RISC-V,并很快建立起一个开源软硬件生态系统。截止 2019 年 1 月,已有包括 Google、NVidia 等在内的 200 多个公司和高校在资助和参与 RISC-V 项目。其中,部分企业已经开始将 RISC-V 集成到产品中。例如全球第一大硬盘厂商西部数据(Western Digital)最近宣布将把每年各类存储产品中嵌入的 10 亿个处理器核换成 RISC-V;Google 利用 RISC-V 来实现主板控制模块;NVidia 也将在 GPU 上引入 RISC-V 等。此外,国内阿里巴巴、华为、联想等公司都在逐步研究各自的 RISC-V 实现;上海市将 RISC-V 列为重点扶持项目;印度政府也正在大力资助基于 RISC-V 的处理器项目,使 RISC-V 成为了印度的事实国家指令集。
由此可见,RISC-V 国内外的兴起使得目前 RISC-V 的生态已经比较完善了。
2019 年度国际计算机体系结构旗舰会议 ISCA 于 6 月在美国亚利桑那州凤凰城召开,会议的主题即是“面向下一代计算的敏捷开放硬件(Agile and Open Hardware for Next-Generation Computing)”。由此可见开放硬件,敏捷开发已成为未来的趋势。而 RISC-V 则刚好成为这趋势中不可或缺的一环。
目前开源硬件开发中面临着 4 个关键问题 (Yungang Bao, Chinese Academy of Sciences, The Four Steps to An Open-Source Chip Design Ecosystem):
RISC-V 便处于第一环中,
虽然目前每个环节都还未完全解决,但我们可以相信,在未来,开发硬件可以像开发一个软件一样。充分利用已开源的资源,用户只需要定制 10% 以内的代码,便可以以月为单位开发出客制化的硬件系统。
为什么单片机可以控制灯的亮灭,通用 PC 却没办法控制灯呢?(因为没有 CPU 到 LED 的接口也没有驱动程序)
中断向量机制和 MIPS 采用的统一入口地址不太一样。中断向量机制硬件产生中断请求时,中断号是确定了的(通过中断控制器发送中断号),软件可以配置对应中断服务程序。而 MIPS 没有中断号的概念,通过软件检查 Stastus 寄存器,来确定是哪一个中断,跳转到对应中断服务程序。
中断向量机制的 CPU 通常需要一个中断控制器,连接在总线上。中断控制器会给 CPU 提供中断号。
MCU 本质就是一个微型计算机,包含 CPU,存储器,I/O 接口(控制器模块)。嵌入式开发就是要基于 MCU 搭建一个硬件系统(通过 MCU 的 I/O 接口连接各种需要被控制的外设),并逐层向上编写构件(驱动),最后基于构件编写嵌入式应用,从而完成需要的功能。
MCU 由于需要通用性,使得用户可以基于 MCU 去搭建自己的系统,驱动自己的外设,因此每个引脚都复用多个功能。通过配置 MCU 内对应控制器的寄存器来配置引脚的功能。
比如 MSP432 100 个引脚中有 84 个可以配置成 GPIO 引脚。只需要将 MSP432 分配的 GPIO 寄存器中的 PxSEL0, PxSEL1 寄存器(x 表示端口号,有 11 个端口 P1~P10 和 PJ)都置为 0 时,该端口的引脚即为 GPIO 功能。同样可以通过配置 GPIO 寄存器控制引脚方向作为输入还是输出,用于点亮 LED 灯或者接受开关输入。
再比如 MSP432 有 4 个增强型通用串行通信接口模块 (eUSCI),也分配了若干寄存器。通过配置寄存器可以将对应引脚配置为 UART 的引脚或 SPI 的引脚。
但是我们在 FPGA 上搭建 SoC 时,开发板上的灯、拨码开关和 FGPA 芯片的引脚是连好了的(由开发板的提供商基于 FPGA 芯片搭建),也就是说每个引脚作为输入还是输出是已经确定了的。我们能改变的只是——是否使用该外设。当然,不排除保留了一些引脚被接到扩展插口上(那一排排的黑色插孔)。因此在 FPGA 上搭建 SoC 后,实现外设驱动需要对外设的控制器进行配置。而嵌入式开发还多出了配置 MCU 内用于复用的模块寄存器。
事实上大端更符合人的思维,因为在写一个数字时人们更习惯从高位写到低位,且高位是写在左边的。而这可以直接和内存的“图像”对应,而小端则需要把每个字的字节地址颠倒一下才可以。 例如,一个 32 位的整数 0xffeeddcc,在内存里的存储情况如下。(非对齐,起始地址为 0x01)
大端: 0 1 2 3 0x00 00ffeedd 0x01 cc556677 小端: 3 2 1 0 0x00 eeddcc00 0x01 776655ff ps.假设除去该整数存储的空间,字节地址与存储的十六进制数对应,即地址为 0x01 存 11,0x05 存 55,这点用来突出字节地址是多少。
instruction lwl/swl, lwr/swr usage lwl t0, offset(s0)
其中的 left,与 shift left 的“左”都表示数据的高位。right 则表示数据的低位。
lwl 表示将内存对应地址所在的字(align_address,即抹掉地址低两位对应地址)的数据低位复制到寄存器数据的高位。寄存器其它部分不变。
swl 则表示将寄存器的数据高位复制到内存对应数据低位。其它部分不变。 即 lwl/swl 寄存器数据高位↹内存数据低位 lwr/swr 寄存器数据低位↹内存数据高位
大端 lwl s0, 0(1) lwr s0, 3(1) 小端 lwr s0, 0(1) lwl s0, 3(1)
将整数以图中所示存储到内存中只需将 lw*改为 sw*。
可以以此定义非对齐加载、存储伪指令, 如 uld(rd, rb) 表示非对齐 load,加载内存[rb+3:rb]的数据, uld(rd, rb)=> lwl rd, 0(rb) lwr rd, 3(rb) (可能 uld 是加载 8 字节,待确认)
n 为地址低 2 位,n=addr[1:0] 大端 lwl/swl 4-n lwr/swr n+1 小端 lwr/swr 4-n lwl/swl n+1
Consider the traffic deadlock depicted in follow figure.
a. Show that the four necessary conditions for deadlock indeed hold in this example. b. State a simple rule for avoiding deadlocks in this system.
Consider a system consisting of four resources of the same type that are shared by three processes, each of which needs at most two resources. Show that the system is deadlock free.
答:反证法,假设形成了死锁。则由每个进程最多需求 2 个资源实例,和死锁必要条件中的 3,4 点可知,唯一的情形是:三个进程各自占有一个资源且等待另一个资源,并形成了一个环。而在该情况下,剩余的一个资源导致死锁不会发生。
Consider a system consisting of m resources of the same type being shared by n processes. Resources can be requested and released by processes only one at a time. Show that the system is deadlock free if the following two conditions hold:
$ a. \sum_{i=1}^n Max_i < m+n $ $ b. Max_i \geq 1 for all i $ $ c. Need_i = Max_i − Allocation_i $
If there exists a deadlock state then: $ d. \sum_{i=1}^n Allocation_i = m $
$ a,b,c,d \Rightarrow \sum_{i=1}^n Need_i < n $
This implies that there exists a process $ P_i $ such that $ Need_i = 0 $. Since $ Max_i >= 1 $, it follows that $ P_i $ has at least one resource, the deadlock can't maintain.
Consider the following snapshot of a system:
PID | AL. | MAX | ||||||
---|---|---|---|---|---|---|---|---|
A | B | C | D | A | B | C | D | |
P0 | 0 | 0 | 1 | 2 | 0 | 0 | 1 | 2 |
P1 | 1 | 0 | 0 | 0 | 1 | 7 | 5 | 0 |
P2 | 1 | 3 | 5 | 4 | 2 | 3 | 5 | 6 |
P3 | 0 | 6 | 3 | 2 | 0 | 6 | 5 | 2 |
P4 | 0 | 0 | 1 | 4 | 0 | 6 | 5 | 6 |
AV. | |||
---|---|---|---|
A | B | C | D |
1 | 5 | 2 | 0 |
(p.s. AL.= Allocated:, AV.= Available)
Answer the following questions using the banker's algorithm: a. What is the content of the matrix Need? b. Is the system in a safe state? c. If a request from process $ P_1 $ arrives for (0,4,2,0), can the request be granted immediately?
Consider a system with four processes$ P_1, P_2, P_3$ and $ P_4 $, and two resources, $ R_1, R_2 $ respectively. Each resource has two instances. Furthermore:
$ P_1 $ allocates an instance of $ R_2 $ , and requests an instance of $ R_1 $ ; $ P_2 $ allocates an instance of $ R_1 $ , and doesn’t need any other resource; $ P_3 $ allocates an instance of $ R_1 $ and requires an instance of $ R_2 $ ; $ P_4 $ allocates an instance of $ R_2 $ , and doesn’t need any other resource. Answer the following questions:
a. Draw the resource allocation graph. b. Is there a cycle in the graph? If yes name it. c. Is the system in deadlock? If yes, explain why. If not, give a possible sequence of executions after which every process completes.
当一个进程位于临界区时,任何其它试图进入临界区的进程都必须在代码中不断地循环。
自旋锁是一种会造成忙等的信号量,在进程等待锁时还需不断运行,占用 cpu 资源。
若干个进程竞争系统资源,最后每个进程都必须得在其它进程释放资源时才能改变状态,因而无法改变状态,造成死锁。 如以下程序在 A,B 同时运行时造成死锁。 A:
B:
Servers can be designed to limit the number of open connections. For example, a server may wish to have only N socket connections at any point in time. As soon as N connections are made, the server will not accept another incoming connection until an existing connection is released. Explain how semaphores can be used by a server to limit the number of concurrent connections. (6.8)
初始化计数型信号量 connection=N
wait() 和 signal() 操作。 信号量可分为计数信号量与二进制信号量。计数信号量值域不受限制,代表系统受限资源的数量。 二进制信号量的值只能为 0 或 1,可表示对临界区的访问权(只能有一个进程位于临界区)。
当没有进程等待时,信号量的 signal() 会对信号量的值加一,而管程里的 signal() 则不会进行任何操作。
A uniprocessor system concurrently executes 2 processes ($ P_A, P_B $). Two Semaphores $ Mutex_R_a $ and $ Mutex_R_b $ are added in mutual accessing the critical section and synchronizing between $ P_A $ and $ P_B $ . Please read following program segment carefully and answer the questions:
(1) What are initial values for $ Mutex_R_a $ and $ Mutex_R_b $ . (2) Is it possible to cause deadlock? Please state your reason. Semaphore $ Mutex_R_a $, $ Mutex_R_b $ ;
Void P_A ( ){
while(true){
Wait(Mutex_Ra );
......
Wait(Mutex_Rb );
......
Signal(Mutex_Ra );
......
Signal(Mutex_Rb );
}
}
Void P_B ( ){
while(true){
Wait(Mutex_Rb );
......
Wait(Mutex_Ra );
......
Signal(Mutex_Rb );
......
Signal(Mutex_Ra );
}
}
答: (1) $ Mutex_R_a = Mutex_R_b = 1$ (2) 当 P_A 和 P_B 同时到达时,两个进程都会执行第一句,接着便会由于$ Mutex_R_a = Mutex_R_b = 0$而陷入死锁。
设有一个可以装 A、B 两种物品的仓库,其容量有限 (为 N),但要求仓库中 A、B 两 种物品的数量满足下述不等式: $$ -M≤A 物品数量-B 物品数量≤N $$ 其中 M 和 N 为正整数。另外,还有一个进程消费 A 和 B,一次取一个 A 与 B 组装成 C。 试用信号量和 P、V 操作描述 A、B 两种物品的入库和出库 (组装成 C) 过程。
答: 设 nA, nB 分别为 A 物品,B 物品数量,二进制信号量 mutex,初始值为 1。
A 入库进程:
B 入库进程:
C 出库进程:
changed:
对于长期调度程序,知道进程是 IO 约束的还是 CPU 约束的之后,便可以按照一定比例组合被调度的进程,使得 CPU 和 IO 设备都会一直处于负载状态,从而提高资源的使用率。 对于短期调度(CPU 调度),IO 约束的进程 CPU 区间都比较短,而 CPU 越苏进程则比较长,因而根据最短作业优先准则,可以优先调度 IO 约束进程。
Process | Burst Time | Priority |
---|---|---|
$ P_1 $ | 10 | 3 |
$ P_2 $ | 1 | 1 |
$ P_3 $ | 2 | 3 |
$ P_4 $ | 1 | 4 |
$ P_5 $ | 5 | 2 |
The processes are assumed to have arrived in the order $ P_1,P_2,P_3,P_4,P_5 $, all at time 0.
FCFS | SJF | nopreemptive priority | RR | |
---|---|---|---|---|
$ P_1 $ | 10 | 19 | 16 | 19 |
$ P_2 $ | 11 | 1 | 1 | 2 |
$ P_3 $ | 13 | 4 | 18 | 7 |
$ P_4 $ | 14 | 2 | 19 | 4 |
$ P_5 $ | 19 | 9 | 6 | 14 |
FCFS | SJF | nopreemptive priority | RR | |
---|---|---|---|---|
$ P_1 $ | 0 | 9 | 6 | 9 |
$ P_2 $ | 10 | 0 | 0 | 1 |
$ P_3 $ | 11 | 2 | 16 | 5 |
$ P_4 $ | 13 | 1 | 18 | 3 |
$ P_5 $ | 14 | 4 | 1 | 9 |
sum | 48 | 16 | 41 | 27 |
- d. Which of the schedules in part a results in the minimal average waiting time (over all processes)? |
答:SJF with 3.2 ms
答:
假设 CPU 按照一定顺序执行这些进程,每个进程 CPU 区间分别为$ t_1,t_2,\dots,t_n $。(非抢占) 则平均等待时间为: $$ \overline t = \frac{1}{n}\sum_{i=1}^n{(i-1)t_i} $$ 由排序不等式知$ t_1,t_2,\dots,t_n $降序时最短,即 SJF 算法。
处理器亲和性指在多处理器调度算法中,由于 cache miss 的代价比较高,应该努力让一个进程在一个处理器上运行。 而负载平衡指将工作负载平均分配到每个处理器上,从而保持每个处理器使用率都比较高。 因此当一个处理器负载较高时,负载平平衡策略会倾向让负载分配到多个处理器上,而处理器亲和则倾向保持该状态。 因此这两种策略有矛盾的关系。
今天去看小黑电影了,发生了许多有趣的事情。
14:20 出门时遇到 lfy 了,他什么都不带要去朝天门玩。我们刚好顺路,都要去三峡广场(sb 地图,推荐我坐半个小时公交车绕路去,幸好 fy 提醒了我走路去,只走了不到 10 分钟就到了)。
到了电影院后,发现电影院其实挺小的,大厅就是等候室,几排火车站的那种椅子。由于我早了 40 多分钟,便坐在那儿等。
入场了,果然来的人很少。我前边只有一对情侣,我右边没人,左边是三个妹纸(怎么感觉有点幸运,“自动变色”),后面我只注意到了一对男生,以及一位年纪好像还挺大的阿姨(难道是真爱?感觉大人看动画电影的只会是一家人的情况呀)。
电影开始了(之前都是黑屏,在开始前 2 分钟开始放广告,如果黑屏的时间里放和小黑有关的宣传片多好呀,不知道首映的时候会不会放)。
播放没几分钟,突然黑屏了。台下开始只言片语起来,只听见左边的三个女生中两个外向点女生调侃第一次出来就运气这么不好,还说还不如去吃东西,接着说要不要去退票。不过中间的女生说她还想看看,她们可以去问问能不能退票(这才是真爱呀,推断应该是她安利她们两个过来看的)。然后最左边的女生便主动出去叫工作人员了。几分钟后设备弄好了,电影继续。
只要你吹罗小黑,我们就是好朋友。 剧情十分紧凑,基本没有什么废话。剧情衔接流畅自然。电影从中间开始,一路炫酷打斗,高潮不断。结尾也不拖沓,风息化作森林,小黑认无限为师父继续流浪,一切都释然了。结尾的也有彩蛋,山新对小白说(山新)说:“早晚有一天你会遇到你生命中的那只猫的”,衔接了 TV 版。
我喜欢小黑的原因就是因为他里面一切都很纯粹,没有坏人,没有阴谋诡计。所以看得十分舒服。电影有丰富有趣的笑点。意境也很美——茂密的森林,鸡犬相闻的乡村,农田,夜晚,星星,大海,繁华的都市,一切都是那么的平衡,都让人感叹世界真美。人物性格鲜活分明。
p.s. 今天晚上 b 站刷小黑的各种周边视频,发现原来这种风格的动画用“治愈”来描述比较合适。
Provide two programming examples in which multithreading does not provide better performance than a single-threaded solution.
1) 任何“线性”执行的程序(后面的程序严重依赖前面执行的结果),这类程序即使使用多线程,每个线程都会阻塞其它线程的执行,因此并不会有更好的性能。
2) 只执行单一任务的程序。多线程对于浏览器,字处理软件等多任务软件是有用的。如浏览器可以在接收网络数据时同时刷新页面。但对于只执行单个任务的程序,便没有必要。
Describe the actions taken by a thread library to context switch between user-level threads.
用户级线程库的代码都存在于用户空间,因此调用库中的函数会导致一个本地调用而不是系统调用。因为线程主要包括寄存器的值和栈,因此上下文切换会涉到寄存器和栈状态的保存和恢复。
Under what circumstances does a multithreaded solution using multiple kernel threads provide better performance than a single-threaded solution on a single-processor system?
1)一个应用程序分为许多不同的部分。如网页浏览器有一个线程用于显示图像和文本,另一个用于从网络接收数据。 2)一个应用程序需要执行多个相似的任务。如网页服务器可能要处理上千个客户并发请求网页。
Which of the following components of program state are shared across threads in a multithreaded process?
答:b,c
Consider a multiprocessor system and a multithreaded program written using the many-to-many threading model. Let the number of user-level threads in the program be more than the number of processors in the system. Discuss the performance implications of the following scenarios.
a. The number of kernel threads allocated to the program is less than the number of processors.
b. The number of kernel threads allocated to the program is equal to the number of processors.
c. The number of kernel threads allocated to the program is greater than the number of processors but less than the number of user-level threads.
答:当内核线程小于处理器数目时,因为用户线程只能通过内核线程访问处理器,因此会有一些处理器处于“围观”状态。当内核线程刚好等于处理器时,处理器的效率相对于 a 会提高,然而当一个线程执行了阻塞系统调用时,其它用户线程就无法使用该内核进程,c 的情况则弥补了这一点,当一个用户线程阻塞时可以被其它用户线程替换,因此处理器效率最高。
Describe the differences among short-term, medium-term, and long-term scheduling.
Describe the actions taken by a kernel to context-switch between processes.
进程间的上下文切换,即切换到另一个进程时需要保留当前进程的状态并恢复另一进程的状态。这些状态可以用 PCB 即进程控制块表示,包含进程状态,程序计数器,CPU 寄存器等信息。上下文切换时,主要执行一个状态保存和状态恢复过程,可能还要执行一些体系结构有关的操作比如清除 cache 等。
Consider a computer with N processors in a multiprocessor configuration.
a. How many processes can be in each of the Ready, Running, and Waiting states at one time? 答:若干个就绪阶段,不超过 N 个执行阶段,若干个等待阶段。 b. What is the minimum number of processes that can be in each of the Ready, Running, and Waiting states at one time? 答:最少当然都是 0 个?
Please explain the five states of a process.
what is the role of PCB in OS? What information is contained in PCB? 操作系统对进程的创建、删除、调度都是通过对 PCB 的操作来完成的。 PCB 包含:
When a process is created, the operating system needs to be done?
Please list the differences between message passing system and shared memory system.
List five services provided by an operating system that are designed to make it more convenient for users to use the computer system. In what cases it would be impossible for user-level programs to provide these services? Explain.
1 程序执行 服务:操作系统将程序装载入内存并执行程序。 若使用用户程序提供该服务,则很有可能带来安全隐患,因为应用程序可能会装载非法程序。
2 I/O 操作 服务:系统提供方便操作 I/O 设备的方法。 若使用用户程序提供该服务,在多用户系统中,应用程序可能会窃取其它用户存储在硬盘里的数据。
3 文件系统操作 服务:提供文件的,创建、删除、搜索、获取信息方法,并提供访问权限管理。 同样,应用程序可能会非法访问文件。
4 通信 服务:提供进程间的相互通信。(同一计算机内的不同进程或通过网络链接的不同计算机的进程) 同样,应用程序可能会非法窃听其它应用的信息。
5 错误检测 服务:对于发生在硬件上或用户程序中的错误,操作系统采取适当的处理措施。 若使用应用程序提供该服务,则应用程序在编写时需要考虑所有可能的错误,这是不现实的。
What are the five major activities of an operating system in regard to file management?
What are the two models of interprocess communication? What are the strengths and weaknesses of the two approaches?
1 共享内存 (shared-memory model) 优点:
缺点:
2 消息 (message-passing model) 优点:
缺点:
Under what circumstances would a user be better off using a timesharing system rather than a PC or single-user workstation? 答:当计算机性能足够强大的时候,采用分时系统可以让计算机同时地,快速地,为许多用户解决复杂的问题,并使得计算资源得到充分的利用。此时若让每个用户使用 pc 机去解决问题会需要很久,而给使用工作站成本又太高。
Describe the differences between symmetric and asymmetric multiprocessing. What are three advantages and one disadvantage of multiprocessor systems? 答:
优点:
缺点:
What is the purpose of interrupts? What are the differences between a trap and an interrupt? Can traps be generated intentionally by a user program? If so, for what purpose? 答:
教材:计算机组成原理:软硬件接口 第 5 版 (mips 版) 时间:2019/09/08
以 C 语言为例: 编译 汇编 链接 $ 源代码 \Longrightarrow 汇编语言 \Longrightarrow 目标代码 \Longrightarrow 机器代码$
a) $ frame size = 1280 \times 1024 \times 3 \times 8bit = 3.75MB $ b) $ time = \frac{ 1280 \times 1024 \times 3 \times 8bit }{100 \times 10^{6} bit} \approx 0.31s $
设\(I\)为指令数,\(t\)为 cpu 执行时间,\(f\)为时钟频率,则: $$ I = \frac{t \cdot f}{CPI} $$ $ I_{p1} = {1 \times 3 \over 1.5} = 2G 条$ $ I_{p2} = {1 \times 2.5 \over 1} = 2.5G 条$ $ I_{p3} = {1 \times 4 \over 2.2} \approx 1.82G 条$
设$ C $为时钟数,则:
$ C_{p1} = 10 \times 3 = 30G $ $ I_{p1} = {30 \over 1.5} = 20G $
$ C_{p2} = 10 \times 2.5 = 25G $ $ I_{p2} = {25 \over 1} = 25G $
$ C_{p3} = 10 \times 4 = 40G $ $ I_{p3} = {40 \over 2.2} \approx 18.2G $
(1) $ t = \frac{I \cdot CPI}{f} $ (2) $ (1-0.3)t = \frac{I \cdot (1+0.2)CPI}{f'} $
$ 由\frac{(1)}{(2)} \Rightarrow \frac{clock rate'}{clock rate} = {(1+0.2) \over (1-0.3)} = 1.71$
令$ p_i $为一条指令占总指令的比例,则对于平均 CPI,有: $$ \overline {CPI} = \sum_{i=1}^nCPI_i \cdot p_i $$ 对于 P1:$ \overline {CPI} = 0.1\times 1 + 0.2\times 2 + 0.5\times 3 + 0.2\times 3 = 2.5 $ 对于 P2:$ \overline {CPI} = 2 $
对于 P1,时钟数:$ C = \frac{1.0 \times 10^6}{2.5} = 4\times 10^5 $ 对于 P2,时钟数:$ C = \frac{1.0 \times 10^6}{2} = 5\times 10^5 $
设$ T \(为时钟周期,\) t \(为程序执行时间,\) I $为指令数,则: $$ CPI = \frac{t}{I \cdot T} $$ $ \overline {CPI_A} = \frac{1.1s}{1.0 \times 10^9 \times 1 ns} = 1.1$ $ \overline {CPI_B} = \frac{1.5s}{1.2 \times 10^9 \times 1 ns} = 1.25$
设$ f = \frac{1}{T} $,利用上述公式,得: $$ \frac{CPI_A}{CPI_B} = \frac{I_B \cdot T_{PB}}{I_A \cdot T_{PA}}\ \Rightarrow \frac{1.1}{1.25} = \frac{1.2 f_{PA}}{1.0 f_{PB}}\ \Rightarrow \frac{f_{PA}}{f_{PB}} = 0.733 $$ 答:处理器 A 的时钟频率为处理器 B 的 0.733 倍
仍假设 cpu 时钟周期为 1ns,$ t_{new} = 6.0 \times 10^8 \times 1.1 \times 1ns = 0.66s $
对于 A: $ 加速比 = (1.1 - 0.66)/1.1 = 40\% $ 对于 B:$ 加速比 = (1.5 - 0.66)/1.5 = 29.3\% $
设 P 为功耗,C 为负载电容,V 为电压,f 为开关频率,动态功耗公式: $$ P = C \cdot U^2 \cdot f $$ $ C_{Pentium 4} = \frac{90}{1.25^2 \times 3.6 \times 10^6} = 16 \mu F$ $ C_{Core i5} = \frac{40}{0.9^2 \times 3.4 \times 10^6} \approx 14.5 \mu F$
$ 设 p1 为静态功耗占总功耗的比例,p2 为静态功耗相对于动态功耗的比例。 $
$ Pentium 4: p1 = 10/100 = 10\%, p2 = 10/90 = 11.1\%$ $ Core i5: p1 = 30/70 = 42.9\%, p2 = 30/40 = 75\%$
对于 P4: $ 90 = 90t^2 + 10t \Rightarrow t \approx 0.946 $ 对于 i5: $ 63 = 40t^2 + 30t \Rightarrow t \approx 0.935$ 答:对于 P4,电压降为原来的$ 94.6\% \(,对于 i5,电压降为原来的\) 93.5\% $