导言
Cache is to reduce latency
GLIBC(GNU C Library)是Linux系统中的标准C库,它提供了许多与程序执行和系统交互相关的功能。GLIBC是应用程序与操作系统之间的接口,提供了许多系统调用的包装函数和其他基础功能,使应用程序能够访问操作系统提供的服务和资源。
GLIBC的主要功能包括:
上下文切换与GLIBC之间没有直接关系。上下文切换是操作系统的概念,是在进程或线程之间切换执行权的过程。GLIBC作为C库,封装了一些系统调用和基础功能,但并不直接参与上下文切换的过程。
然而,GLIBC的性能和效率可以影响上下文切换的开销。GLIBC的实现方式、性能优化以及与操作系统内核的协作方式,可能会对上下文切换的效率产生影响。例如,GLIBC的线程库(如pthread)的设计和性能特性,以及对锁、条件变量等同步原语的实现方式,都可能会影响多线程上下文切换的开销。
因此,尽管GLIBC本身不直接执行上下文切换,但它的设计和实现对于多线程编程和系统性能仍然具有重要的影响。
在PPA。改系统的glibc十分的危险,ssh连接,ls命令等,都需要用到。会导致ssh连接中断等问题。
不推荐,可能会遇到库依赖。比如缺少bison和gawk。详细依赖见
1 | mkdir $HOME/glibc/ && cd $HOME/glibc |
您可以使用以下方法来查找libstdc++库的位置:
g++或gcc命令查找:如果您的系统上安装了g++或gcc编译器,您可以使用以下命令来查找libstdc++库的位置:1 | g++ -print-file-name=libstdc++.so |
或者
1 | gcc -print-file-name=libstdc++.so |
ldconfig命令查找:ldconfig是Linux系统中用于配置动态链接器的命令。您可以运行以下命令来查找libstdc++库的路径:1 | ldconfig -p | grep libstdc++.so |
/usr/lib或/usr/lib64。您可以在这些目录中查找libstdc++的库文件。如果您找到了libstdc++库的路径,您可以将其添加到CMakeLists.txt中的CMAKE_CXX_FLAGS变量中,如之前的回答中所示。
请注意,如果您正在使用的是Clang编译器(clang++),则默认情况下它将使用libc++作为C++标准库,而不是libstdc++。如果您确实希望使用libstdc++,需要显式指定使用-stdlib=libstdc++标志。例如:
1 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") |
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无
LLVM项目开始于一种比Java字节码更低层级的IR,因此,初始的首字母缩略词是Low Level Virtual Machine。它的想法是发掘低层优化的机会,采用链接时优化。

学过编译原理的人都知道,编译过程主要可以划分为前端与后端:
经典的编译器如gcc:在设计上前端到后端编写是强耦合的,你不需要知道,无法知道,也没有API来操作它的IR。
好处是:因为不需要暴露中间过程的接口,编译器可以在内部做任何想做的平台相关的优化。
坏处是,每当一个新的平台出现,这些编译器都要各自为政实现一个从自己的IR到新平台的后端。
LLVM的核心设计了一个叫 LLVM IR 的通用中间表示, 并以库(Library) 的方式提供一系列接口, 为你提供诸如操作IR、生成目标平台代码等等后端的功能。
在使用通用IR的情况下,如果有M种语言、N种目标平台,那么最优情况下我们只要实现 M+N 个前后端。
LVM IR实际上有三种表示:
各种格式是如何生成并相互转换:
| 格式 | 转换命令 |
|---|---|
| .c -> .ll | clang -emit-llvm -S a.c -o a.ll |
| .c -> .bc | clang -emit-llvm -c a.c -o a.bc |
| .ll -> .bc | llvm-as a.ll -o a.bc |
| .bc -> .ll | llvm-dis a.bc -o a.ll |
| .bc -> .s | llc a.bc -o a.s |
对于LLVM IR来说,.ll文件就相当于汇编,.bc文件就相当于机器码。 这也是llvm-as和llvm-dis指令为什么叫as和dis的缘故。

clang实现的前端包括
见 llvm Backend 一文
Clang 是 LLVM 项目中的一个 C/C++/Objective-C 编译器,它使用 LLVM 的前端和后端进行代码生成和优化。它可以将 C/C++/Objective-C 代码编译为 LLVM 的中间表示(LLVM IR),然后进一步将其转换为目标平台的机器码。Clang 拥有很好的错误信息展示和提示,支持多平台使用,是许多开发者的首选编译器之一。同时,Clang 也作为 LLVM 项目的一个前端,为 LLVM 的生态系统提供了广泛的支持和应用。
Clang 的开发起源于苹果公司的一个项目,即 LLVM/Clang 项目。在 2005 年,苹果公司希望能够使用一种更加灵活、可扩展、优化的编译器来替代 GCC 作为其操作系统 macOS (Mac OS X) 开发环境的默认编译器。由于当时的 GCC 开发被其维护者们认为变得缓慢和难以维护,苹果公司决定开发一款新的编译器,这就是 Clang 诞生的原因。Clang 的开发团队由该项目的创立者 Chris Lattner 领导,他带领团队将 Clang 发展为一款可扩展、模块化、高效的编译器,并成功地将其嵌入到苹果公司的开发工具链 Xcode 中,成为了 macOS 开发环境中默认的编译器之一。
Clang 是一个开源项目,在苹果公司的支持下,Clang 的开发得到了全球各地的开发者们的广泛参与和贡献。现在,Clang 成为了 LLVM 生态中的一个重要组成部分,被广泛地应用于多平台的编译器开发中。
Clang and Clang++ “borrow” the header files from GCC & G++. It looks for the directories these usually live in and picks the latest one. If you’ve installed a later GCC without the corresponding G++, Clang++ gets confused and can’t find header files. In your instance, for example, if you’ve installed gcc 11 or 12.
You can use clang-10 -v -E or clang++-10 -v -E to get details on what versions of header files it’s trying to use.
安装g++-12解决
github/tools目录下有许多实用工具
llvm-as:把LLVM IR从人类能看懂的文本格式汇编成二进制格式。注意:此处得到的不是目标平台的机器码。llvm-dis:llvm-as的逆过程,即反汇编。 不过这里的反汇编的对象是LLVM IR的二进制格式,而不是机器码。opt:优化LLVM IR。输出新的LLVM IR。llc:把LLVM IR编译成汇编码。需要用as进一步得到机器码。lli:解释执行LLVM IR。暂无
暂无
文章部分内容来自ChatGPT-3.5,暂时没有校验其可靠性(看上去貌似说得通)。
将一件事情分成若干阶段,然后通过阶段之间的转移达到目标。由于转移的方向通常是多个,因此这个时候就需要决策选择具体哪一个转移方向。
动态规划所要解决的事情通常是完成一个具体的目标,而这个目标往往是最优解。并且:
每个阶段抽象为状态(用圆圈来表示),状态之间可能会发生转化(用箭头表示)。可以画出类似如下的图:

性质:
对于一个能用动态规划解决的问题,一般采用如下思路解决:
如何找到转移关系:
背包DP
f[i,0]=1f[i,0]=1n[i] 为 13,就将这种物品分成系数分别为 1, 2, 4, 6 的 4 件物品。1 | int num[maxn][2], dp[maxn]; |
区间DP
DAG 上的DP
树形 DP 往往需要递归DFS
爬楼梯问题的暴力普通递归DFS代码
1 | function climbStairs(n) { |
添加与DFS参数相关的记忆化数组,将这个 dfs 改成「无需外部变量」的 dfs。
1 | memo = {} |
状压+动态规划(DP, Dynamic Programming)
使用的数有限(共 10 个),并且使用到的数最多出现一次,容易想到使用「状压 DP」来求解:我们使用一个二进制数来表示具体的子集具体方案。
定义 f[state] 为当前子集选择数的状态为 state 时的方案数,state 为一个长度 10 的二进制数,若 state 中的第 k 位二进制表示为 1,代表数值 p[k] 在好子集中出现过;若第 k 位二进制表示为 0 代表 p[k] 在好子集中没出现过。
状态压缩有关,比如用 4 个字节存储状态
动态规划 与 np完全的关系
暂无
视频: https://www.bilibili.com/video/BV1Xj411K7oF/?vd_source=5bbdecb1838c6f684e0b823d0d4f6db3
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
实例化:创建一个类的实例,类的具体对象。
方法:类中定义的函数。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
在Python中,类变量和实例变量是两个不同的概念:
例如:
1 | class Person: |
综上,类变量用于定义类的通用属性,实例变量用于定义实例的独特属性。区分二者是理解Python面向对象的关键。
1 | class Employee: |
必须有一个额外的第一个参数名称, 按照惯例它的名称是 self,self 不是 python 关键字,换成其他词语也行。
1 | emp1 = Employee("Zara", 2000) |
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
继承语法 class 派生类名(基类名)
调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数
,这点在代码上的区别如下:
1 | class Base: |
在Derived类中:
调用Base基类的方法base_method(),需要写成Base.base_method(self)
调用普通函数print(),直接写函数名即可
区别在于:
而对于普通函数,只需要直接调用即可,不需要self参数。
这与Python的名称空间和面向对象实现有关,是理解Python类继承的关键点。
1 | __init__ : 构造函数,在生成对象时调用 |
在Python中可以通过特殊方法__iadd__来对+=符号进行重载。
__iadd__需要定义在类中,用于指定+=操作时的具体行为。例如:
1 | class Vector: |
这里我们定义了__iadd__方法,用于实现两个Vector对象使用+=时的相加操作。
__iadd__方法的参数是另一个要相加的对象,在方法内部我们实现了两个向量的分量相加,并返回self作为结果。这样就实现了+=的运算符重载。
此外,Python还提供了__add__特殊方法用于重载+符号,但是__iadd__和__add__有以下区别:
所以对可变对象进行+=操作时,通常需要实现__iadd__方法。
According to 2007 paper
进程或线程的上下文切换可以在多种情况下发生,下面列举了一些常见的情况:
需要注意的是,上下文切换是操作系统内核的责任,它根据调度策略和内核的算法来管理进程和线程的切换。上下文切换的具体发生时机和行为取决于操作系统的设计和实现。
保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。
包括以下几个方面:
相对于进程上下文切换,线程上下文切换通常更快,这是因为线程共享相同的地址空间和其他资源,因此上下文切换只需要切换线程的执行状态和部分寄存器,省去了一些额外的开销。
以下是线程上下文切换相对于进程上下文切换的一些优势和省去的时间开销:
尽管线程上下文切换相对较快,但仍然需要一些时间和开销,包括以下方面:
需要注意的是,线程上下文切换的快速性是相对于进程上下文切换而言的,具体的开销和时间取决于系统的设计、硬件的性能和操作系统的实现。不同的操作系统和硬件平台可能会有不同的上下文切换开销。
如果要能清晰的回答这一点,需要对OS的页表管理和上下午切换的流程十分了解。
Page Table Isolation(页面表隔离)是一种为了解决Meltdown等CPU安全漏洞而提出的硬件优化机制。
其主要思想是将操作系统内核和用户空间的页面表隔离开来,实现内核地址空间与用户地址空间的隔离。
具体来说,Page Table Isolation 主要包括以下措施:
这种机制可以阻止用户程序直接读取内核内存,防止Meltdown类攻击获得内核敏感信息。
当前主流的x86处理器通过在TLB中添加PTI(Page Table Isolation)位实现了此机制,来隔离内核地址空间。这成为了重要的安全优化之一。
由于PTI的存在,内核维护了两套 页表。
用户态切换的额外开销包括:
进程上下文标识符(PCID) 是一项 CPU 功能,它允许我们在切换页表时通过在 CR3 中设置一个特殊位来跳过刷新整个 TLB。这使得切换页表(在上下文切换或内核进入/退出时)更便宜。但是,在支持 PCID 的系统上,上下文切换代码必须将用户和内核条目都从 TLB 中清除。用户 PCID TLB 刷新将推迟到退出到用户空间,从而最大限度地降低成本。有关PCID / INVPCID详细信息,请参阅 intel.com/sdm。
在没有 PCID 支持的系统上,每个 CR3 写入都会刷新整个 TLB。这意味着每个系统调用、中断或异常都会刷新 TLB
对于同一个进程的不同线程,当它们运行在不同的物理核心上时,其Intel PCID (进程上下文ID)是相同的。
主要原因如下:
PCID是用于区分不同进程地址空间的标识符。同一进程的线程共享相同的地址空间。
所以操作系统会为同一进程的所有线程分配相同的PCID,无论它们运行在哪个物理核心上。
当线程在物理核心之间迁移时,不需要改变PCID,因为地址空间没有改变。
线程迁移后,新的核心会重新使用原有的PCID加载地址翻译表,而不是分配新的PCID。
这确保了同进程不同线程使用统一的地址映射,TLB内容可以直接重用,无需刷新。
相反,不同进程之间必须使用不同的PCID,才能隔离地址映射,避免TLB冲突。
所以操作系统只会在进程切换时改变PCID,而线程切换保持PCID不变。
综上,对于同一进程的不同线程,无论运行在哪个物理核心,其PCID都是相同的。这使线程可以重用TLB项,是多线程架构的重要优化手段。同进程线程使用统一PCID,不同进程必须使用独立PCID。
PCID(Process Context Identifier)和 ASID(Address Space Identifier)都是用于优化页表切换的技术
Quantifying the cost of context switch
sched setaffinity() and sched setscheduler()SCHED FIFO and give them the maximum priority.1 | # shaojiemike @ hades0 in ~/github/contextSwitch2007 on git:master x [15:59:39] C:10 |
us microseconds, 论文里是3.8 us,我们的机器是0.85 us。Tsuna的2010年的博客
code in https://github.com/tsuna/contextswitch 机器配置在实验结果后。
gettid()futex来切换。包含futex system calls.开销sched_yield让出CPU使用权,强制发生进程切换.futex.只不过线程通过 pthread_create创建来执行函数, 而不是forkshed_yield().并且设置SCHED_FIFO 和 sched_prioritysched_yield()函数的作用是使当前进程放弃CPU使用权,将其重新排入就绪队列尾部。但是如果就绪队列中只有这一个进程,那么该进程会立即再次获得CPU时间片而继续执行。必须有其他等待进程且满足调度条件才会真正发生切换。1 | # snode6 |
如上,snode6应该是550ns
| machine | system calls | process context switches | thread context switches | thread context switches 2 |
|---|---|---|---|---|
| snode6 | 428.6 | 2520.3 | 2606.3(1738.9) | 277.8 |
| snode6 | 427.7 | 2419.8 | 2249.0(2167.9) | 401.1 |
| snode6 | 436.0 | 2327.1 | 2358.8(1727.8) | 329.3 |
| hades | 65.8 | 1806.4 | 1806.4 | 64.6 |
| hades | 65.5 | 1416.4 | 1311.6 | 282.7 |
| hades | 80.8 | 2153.1 | 1903.4 | 64.3 |
| icarus | 74.1 | 1562.3 | 1622.3 | 51.0* |
| icarus | 74.1 | 1464.6 | 1274.1 | 232.6* |
| icarus | 73.9 | 1671.8 | 1302.1 | 38.0* |
| vlab | 703.4 | 5126.3 | 4897.7 | 826.1* |
| vlab | x | x | x | x |
| vlab | 697.1 | 10651.4 | 4476.0 | 843.9* |
| docker |||| | ||||
| docker |||| | ||||
| docker |||| |
说明:
No CPU affinity 和 With CPU affinity 和 With CPU affinity to CPU 0()内为。额外添加设置SCHED_FIFO 和 sched_priority的结果。* 意味着没有sudo权限。报错sched_setscheduler(): Operation not permittedx 报错taskset: 设置 pid 30727 的亲和力失败: 无效的参数问题:
shed_yield().并且设置SCHED_FIFO 和 sched_priority运行strace -ff -tt -v taskset -a 1 ./timetctxsw2. 应该是不需要strace的,为什么需要记录syscall的信息呢?
1 | # snode6 |
猜想:
1 | shaojiemike @ snode6 in ~/github/contextswitch on git:master o [19:46:27] |
| machine | OS | linux kernel | compile | glibc |
|---|---|---|---|---|
| snode6 | Ubuntu 20.04.6 LTS | 5.4.0-148-generic | gcc 9.4.0 | GLIBC 2.31 |
| hades | Ubuntu 22.04.2 LTS | 5.15.0-76-generic | gcc 11.3.0 | GLIBC 2.35-0ubuntu3.1 |
| icarus | Ubuntu 22.04.2 LTS | 5.15.0-75-generic | gcc 11.3.0 | GLIBC 2.35-0ubuntu3.1 |
| vlab | Ubuntu 22.04.2 LTS | 5.15.81-1-pve | gcc 11.3.0 | GLIBC 2.35-0ubuntu3.1 |
glic 版本使用ldd --version获得。OS影响调度算法,内核影响切换机制,编译器影响代码优化,GLIBC影响系统调用开销。
sched_setscheduler() 是一个用于设置进程调度策略的函数。它允许您更改进程的调度策略以及与之相关的参数。具体来说,sched_setscheduler() 函数用于将当前进程(通过 getpid() 获取进程ID)的调度策略设置为实时调度策略(SCHED_FIFO)。实时调度策略是一种优先级调度策略,它将进程分配给一个固定的时间片,并且仅当进程主动释放 CPU 或者其他高优先级的实时进程出现时,才会进行上下文切换。/sys/bus/node/devices/node0/cpumap 存储了与特定 NUMA 节点(NUMA node)关联的 CPU 核心映射信息。cpumap 文件中的内容表示与 node0 相关的 CPU 核心的映射。每个位置上的值表示相应 CPU 核心的状态,常见的取值有:node0。node0。1 | # shaojiemike @ snode6 in ~/github/contextswitch on git:master x [22:37:41] C:1 |
根据1996的论文,需要考虑几个方面的内容:
http://lmbench.sourceforge.net/cgi-bin/man?keyword=lmbench§ion=8
#include <unistd.h> /pipe()的父子进程的write和read system calls实验环境:
根据Light-weight Contexts的数据:
注意,括号内为十次执行的标准差
解释与组成
在测量上下文切换开销时,进程和线程的切换开销可能会相对接近,这可能是由于以下几个原因:
TLB(Translation Lookaside Buffer)的刷新:TLB是用于高速缓存虚拟地址到物理地址映射的硬件结构。当发生进程或线程切换时,TLB中的缓存项可能需要刷新,以确保新的地址映射有效。虽然线程切换只涉及部分的TLB刷新,但刷新的开销相对较小,因此在总的上下文切换开销中可能没有明显拉开差距。
寄存器和上下文切换:无论是进程切换还是线程切换,都需要保存和恢复一部分寄存器的状态和执行上下文。这部分的开销在进程和线程切换中是相似的。
内核操作和调度开销:无论是进程还是线程切换,都需要涉及内核的操作和调度。这包括切换内核栈、更新调度信息、切换上下文等操作,这些开销在进程和线程切换中也是相似的。
需要注意的是,实际上下文切换的开销是受到多个因素的影响,如处理器架构、操作系统的实现、硬件性能等。具体的开销和差距会因系统的不同而有所差异。在某些情况下,线程切换的开销可能会稍微小一些,但在其他情况下,可能会存在较大的差距。因此,一般情况下,不能简单地将进程和线程的上下文切换开销归为相同或明显不同,具体的测量和评估需要结合实际系统和应用场景进行。
暂无
PIM 最优调度遇到的问题
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
Quantifying The Cost of Context Switch 2007,ExpCS
lmbench: Portable tools for performance analysis,1996 USENIX ATC
Light-weight Contexts: An OS Abstraction for Safety and Performance
参考 kernel 文档
面向过程是一种以事件为中心的编程思想,编程的时候把解决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步的具体步骤中再按顺序调用函数。
在日常生活或编程中,简单的问题可以用面向过程的思路来解决,直接有效,但是当问题的规模变得更大时,用面向过程的思想是远远不够的。所以慢慢就出现了面向对象的编程思想。世界上有很多人和事物,每一个都可以看做一个对象,而每个对象都有自己的属性和行为,对象与对象之间通过方法来交互。面向对象是一种以“对象”为中心的编程思想,把要解决的问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个对象在整个解决问题的步骤中的属性和行为。
优点:
缺点:
优点:
缺点:
静态类型语言的
动态类型语言的
runtime 描述了程序运行时候执行的软件/指令, 在每种语言有着不同的实现。
可大可小,在 C 中,runtime 是库代码, 等同于 C runtime library,一系列 C 程序运行所需的函数。
在 Java 中,runtime 还提供了 Java 程序运行所需的虚拟机等。
总而言之,runtime 是一个通用抽象的术语,指的是计算机程序运行的时候所需要的一切代码库,框架,平台等。
在 Go 中, 有一个 runtime 库,其实现了垃圾回收,并发控制, 栈管理以及其他一些 Go 语言的关键特性。 runtime 库是每个 Go 程序的一部分,也就是说编译 Go 代码为机器代码时也会将其也编译进来。所以 Go 官方将其定位偏向类似于 C 语言中的库。
Go 中的 runtime 不像 Java runtime (JRE, java runtime envirement ) 一样,jre 还会提供虚拟机, Java 程序要在 JRE 下 才能运行。
作为支持指针的编程语言,C++将动态管理存储器资源的便利性交给了程序员。在使用指针形式的对象时(请注意,由于引用在初始化后不能更改引用目标 的语言机制的限制,多态性应用大多数情况下依赖于指针进行),程序员必须自己完成存储器的分配、使用和释放,语言本身在此过程中不能提供任何帮助。
某些语言提供了垃圾回收机制,也就是说程序员仅负责分配存储器和使用,而由语言本身负责释放不再使用的存储器,这样程序员就从讨厌的存储器管理的工作中脱身了。
C++的设计者Bjarne Stroustrup对此做出过解释:
“我有意这样设计C++,使它不依赖于自动垃圾回收(通常就直接说垃圾回收)。这是基于自己对垃圾回收系统的经验,我很害怕那种严重的空间和时间开销,也害怕由于实现和移植垃圾回收系统而带来的复杂性。还有,垃圾回收将使C++不适合做许多底层的工作,而这却正是它的一个设计目标。但我喜欢垃圾回收 的思想,它是一种机制,能够简化设计、排除掉许多产生错误的根源。
需要垃圾回收的基本理由是很容易理解的:用户的使用方便以及比用户提供的存储管理模式更可靠。而反对垃圾回收的理由也有很多,但都不是最根本的,而是关于实现和效率方面的。
已经有充分多的论据可以反驳:每个应用在有了垃圾回收之后会做的更好些。类似的,也有充分的论据可以反对:没有应用可能因为有了垃圾回收而做得更好。
并不是每个程序都需要永远无休止的运行下去;并不是所有的代码都是基础性的库代码;对于许多应用而言,出现一点存储流失是可以接受的;许多应用可以管理自己的存储,而不需要垃圾回收或者其他与之相关的技术,如引用计数等。
我的结论是,从原则上和可行性上说,垃圾回收都是需要的。但是对今天的用户以及普遍的使用和硬件而言,我们还无法承受将C++的语义和它的基本库定义在垃圾回收系统之上的负担。”
1.强类型语言:使之强制数据类型定义的语言。没有强制类型转化前,不允许两种不同类型的变量相互操作。强类型定义语言是类型安全的语言,如Rust, Java、C# 和 Python,比如Java中“int i = 0.0;”是无法通过编译的;
2.弱类型语言:数据类型可以被忽略的语言。与强类型语言相反, 一个变量可以赋不同数据类型的值,允许将一块内存看做多种类型,比如直接将整型变量与字符变量相加。**C/C++**、PHP都是弱类型语言,比如C++中“int i = 0.0;”是可以编译运行的;
注意,强类型语言在速度上略逊色于弱类型语言,使用弱类型语言可节省很多代码量,有更高的开发效率。而对于构建大型项目,使用强类型语言可能会比使用弱类型更加规范可靠。
a data-parallel languagedesigned specifically to target Intel’s vector extensions
Intel® Implicit SPMD Program Compiler
An open-source compiler for high-performance SIMD programming on the CPU and GPU
ispc is a compiler for a variant of the C programming language, with extensions for “single program, multiple data“ (SPMD) programming.
暂无
暂无
https://blog.csdn.net/yuanmengong886/article/details/52572533
Mathematical Logic & Algebraic structure
启发来源^1
与排除自指的数学体系类型论
(即使排除了自指,还是不完备的)
数理逻辑的奥秘在于,它试图将人类主观的推理思维过程客观化,并建立起主观推理与客观证明之间的联系。通过对形式语言的公理化来达到自然语言的公理化目标。
存在一个数 = 存在最小的在抽象代数里,代数结构(algebraic structure)是指装备了一个及以上的运算(最一般地,可以允许有无穷多个运算)的非空集合。一般研究的代数结构有群、环、域、格、模、域代数和向量空间等等。在数学中,更具体地说,在抽象代数中,代数结构是一个集合(称为载体集或底层集合),它在它上定义了一个或多个满足公理的有限运算。
暂无
暂无
秋招,百度的高铁柱面试官说,定义问题是很关键的一件事。能不能形式化的定义。(我已经很久没有注意这件事了,确实很重要。
[^2]: wiki First-order logic
线程在核间切换的开销是极小的(Java uses lots of threads but threads have become significantly faster and cheaper with the NPTL in Linux 2.6.),与其考虑切换开销,不如注意不同优先级线程同一个核竞争的问题。
在C++中,有几种方式可以实现线程的创建。下面是一些常见的方法:
std::thread 类这是C++11标准引入的线程库,使用起来非常方便。你可以直接创建一个 std::thread 对象并传递一个函数或可调用对象(如lambda表达式)。
示例代码:
1 |
|
std::async 和 std::futurestd::async 可以用于异步执行任务,返回一个 std::future 对象,你可以通过这个对象获取任务的执行结果。
示例代码:
1 |
|
在使用较早的C++版本或在一些特定的操作系统(如Linux)下,pthread 是创建和管理线程的常用方式。需要包含 <pthread.h> 头文件。
示例代码:
1 |
|
Boost库提供了丰富的线程管理功能,使用起来与标准库类似,但需要安装Boost库。
示例代码:
1 |
|
可以直接调用操作系统提供的API来创建线程,例如在Windows上使用 CreateThread,在Unix/Linux上使用 pthread_create。
Windows上的示例代码:
1 |
|
std::thread 是最常用和推荐的方式,简单易用且跨平台。std::async 更适合用于需要返回值的异步操作。pthread 适合在类Unix系统上使用,适应性强但需要更多的低层管理。线程独占的信息很少,一般就是线程名的获取和设置。
1 |
|
taskset -c 0-4 {command},可以实现命令绑定在编号0-3核上。c++内通过pthread_setaffinity_np函数实现。* `htop -p pid` 里 `a` 选项可以显示已有的亲和性设置
* `ps -p pid` 可以看见CMD相同。
ssh config & X11 & jump-machine
1 | Host node5 |
1 | sudo journalctl -u ssh --since "yesterday" |less |
windows use mobaxterm, mac use xquartz + iterms
1 | ssh -Y [email protected] |
在管理外网服务器时,出于安全等因素的考虑,我们一般不会把所有服务器都设置成可ssh直连,而是会从中挑选出一台机器作为跳板机,当我们想要连接外网服务器时,我们要先通过ssh登录到跳板机,再从跳板机登录到目标服务器。
1 | $ eval $(ssh-agent) |
1 | ssh -A [email protected] |
或者直接
1 | ssh -J [email protected] [email protected] |
这条命令将会首先连接到 [email protected] 的跳板机,然后再通过跳板机连接到 [email protected] 的目标服务器。
1 | scp -J [email protected] [email protected]:/path/to/source/file /path/to/destination/file |
这个命令将会通过 [email protected] 的跳板机从源文件 /path/to/source/file 复制数据到 [email protected] 的目标文件 /path/to/destination/file。
1 | Host <name> |
check is ssh use direct connect not use jump host
google check ssh gui x11 use jump host
https://www.ibm.com/support/pages/how-forward-x11-client-through-jump-host-back-pc-x-emulator
/etc/ssh/sshd_configxauthDISPLAY and XAUTHORITY will automatically be set to their proper values.DISPLAY is not set, it means ssh is not forwarding the X11 connection.ForwardX11 yes in ~/.ssh/configX11UseLocalhost yesvlab 能正常登录的情况下ssh -i D:\\PowerShell\\vlab-vm7096.pem [email protected]
有两种设置ssh config设置方法
1 | Host jumpSnode6Ipv4W |