Java Reference
总结一些Java常用的集合接口以及一些工具类。
Java Collections 类
Collection is the root interface in the collection hierarchy. A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered. The JDK does not provide any direct implementations of this interface: it provides implementations of more specific subinterfaces like Set and List. This interface is typically used to pass collections around and manipulate the ...
Rich Recoverable Error Handling with llvm::Expected<T>
从llvm::Expected的源码中学习一种实用的C++异常处理方式
构建LLVM交叉编译工具链
编译前准备
编译前需要在 llvm 的源码根目录下新建一个 build 目录,然后进入这个目录进行 make,这个主要原因是 LLVM 目前不支持在 llvm-project 目录下直接编译,否则会失败,官方的说法是 in-tree build is not supported。这个 build 目录官方的正式定义叫 OBJ_ROOT,所有 cmake 生成的项目配置文件,以及编译过程中生成的 .o 文件和最终的 bin 文件都会存放在这个目录下。
$ mkdir build$ cd build
使用 cmake 的基本命令模板如下:
$ cd OBJ_ROOT$ cmake -G <generator> [options] SRC_ROOT
其中:
generator表示用于最终驱动gcc执行编译生成llvm的工具,是用双引号括起来的字符串,cmake支持跨平台开发,有以下四种选项:
Unix Makefiles: 即采用Unix上传统的Make,指定该选项后cmake负责生成用于Make的makefile文件。
Ninja: 采用Ninja,指定该选项后 cmak ...
基于SVM的文本分类
最近在做一个简单的小项目,基于SVM的专利文本分类。这里记录一下整个过程。
文本分类主要分为四个步骤:
文本特征提取
文本特征表示
归一化处理
文本分类
1. 特征提取
特征提取的步骤可以总结为:
对全部训练文档进行分词,由这些词作为向量的维数来表示文本;
统计每一类内文档所有出现的词语及其频率,然后过滤,剔除停用词和单字词;
统计每一类内出现词语的总词频,并取其中的若干个频率最高的词汇作为这一类别的特征词集;
去除每一类别中都出现的词,合并所有类别的特征词集,形成总特征词集。最后所得到的特征词集就是我们用到的特征集合,再用该集合去筛选测试集中的特征。
关于Python的文本处理,用得最多的是以下两个库:
NLTK(自然语言工具包):用于诸如分词,词法去除,词干提取,解析,POS标记等任务。该库具有用于几乎所有NLP任务的工具。
spaCy:是NLTK的主要竞争对手。这两个库可用于相同的任务。
NLTK更具学术性,你可以使用它尝试不同的算法,将它们组合起来,等等。spaCy则为每个问题提供了一种即用的解决方案。你不必考虑哪种方法更好,spaCy的作者已经考虑了这一点。并且 ...
深入浅出OS的内存管理
聊聊OS中的内存管理,不侧重原理,侧重实现。
1. 链接、装载
1.1 可执行文件格式
目前主流的可执行文件(Executable File)格式主要有:
Linux的ELF(Executable Linkable Format)。
Windows的PE(Portable Executable)。
编译器将源代码编译后得到的中间文件叫做目标文件。然后再由链接器将目标文件以及它们的所依赖的库链接起来,就得到了最终的可执行文件。目标文件与可执行文件的格式几乎是一样的,所以我们可以将它们看做是同一种类型的文件。
除了可执行文件和目标文件按照可执行文件的格式存储之外,动态链接库(DLL,Dynamic Linking Library)和静态链接库文件也都按照可执行文件的格式存储。
下面的表格总结了这几种文件在Linux和Windows系统中常用的后缀名。
可执行文件
目标文件
动态链接库
静态链接库
Linux
.out或无后缀
.o
.so
.a
Windows
.exe
.obj
.dll
.lib
ELF文件标准还将各种采用ELF格式的文件归为4类,如下表 ...
使用Docker编译32位Linux内核并在Qemu中运行
本文主要介绍在 MacOS 上使用 qemu 搭建 Linux Kernel 的开发环境。(在开始之前需要注意的是,本文中的 Linux 开发环境是基于 Docker 搭建的,而 qemu 通过 homebrew 源码编译安装在本地的 MacOS 上)
1. 为什么需要 qemu?
qemu 是一个硬件虚拟化程序(hypervisor that performs hardware virtualization),与传统的 VMware / VirtualBox 之类的虚拟机不同,它可以通过 binary translation 模拟各种硬件平台(比如在 x86 机器上模拟 ARM 处理器)。而 VirtualBox 等更多是通过虚拟化来进行资源隔离,以便在其上运行多个 guest os。
基于 qemu 的硬件模拟能力,我们可以轻松搭建指定硬件平台的运行实验环境。
qemu 与 VirtualBox 另一个不同点在于,在 VirtualBox 上必须安装一个完整的操作系统套件,而通过 qemu 我们可以通过参数直接启动到一个裸的 Linux Kernel,连 bootloader 都 ...
软件设计原则
本文转载自blinkfox的博客,总结了常用的软件设计原则,对于工程上来说很有指导意义。
一、前言
软件也像人一样,具有生命力,从出生到死亡,会经历多种变化。软件架构设计也不是一蹴而就的,是不断地演进发展。每个程序员都可以从理解编程原则和模式中受益。
软件设计原则是一组帮助我们避开不良设计的指导方针。根据Robert Martin的理论,应该避免不良设计的以下三个重要特点:
僵化:很难做改动,因为每一个细微的改动都会影响到系统大量的其他功能
脆弱:每当你做一次改动,总会引起系统中预期之外的部分出现故障
死板:代码很难在其他应用中重用,因其不能从当前应用中单独抽离出来
下面这些软件设计原则是我从一些书籍和网络中收集而来,并不完整,而且你也需要在一些有“冲突的原则”之间进行权衡和取舍。本文或许会对你的编程、程序设计、讨论或评审工作有所帮助。
二、通用设计原则
1. KISS
所谓KISS原则,即:Keep It Simple,Stupid,指设计时要坚持简约原则,避免不必要的复杂化,并且易于修改。
Everything should be made as simple as p ...
跟随一条指令来看LLVM的基本结构
LLVM是一个很复杂的软件,了解LLVM的工作原理不是很容易,然而,对于刚开始接触LLVM整个框架的工作原理来说,详细而深入,不如广泛而浅显,所以有了这一篇文章。
通过跟随一条指令在LLVM中的各个passes中的状态变化,从源程序开始,到目标代码结束,可以让我们对LLVM的整体框架有个大致的认识。
这篇文章基于Life of an instruction in LLVM,文章大部分内容与参考文章一致,但由于参考文章编辑于2012年11月,当时的LLVM版本是3.2,距现在新的LLVM版本已有一些差异,所以有部分内容我做了调整。
这篇文章不会详细讲解各个passes中的实现,尽量易于理解,尽量紧贴指令的变化过程。
有关于LLVM中的一些基本概念,可以参考:https://blog.csdn.net/SiberiaBear/article/details/103111028。
输入代码
使用的输入代码与参考文章一致,选择一段C语言来开始:
int foo(int aa, int bb, int cc) {int sum = aa + bb;return sum / cc; ...
LeetCode-307. 区域和检索 - 数组可修改
给你一个数组 nums ,请你完成两类查询。
其中一类查询要求 更新 数组 nums 下标对应的值
另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 ,其中 left <= right
实现 NumArray 类:
NumArray(int[] nums) 用整数数组 nums 初始化对象
void update(int index, int val) 将 nums[index] 的值 更新 为 val
int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], ..., nums[right])
示例 1:
输入:["NumArray", "sumRange", "update", "sumRange"][[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]输出:[null, 9, null, 8]解释:NumArray nu ...
自定义LLVM中的PASS
所有的LLVM pass都是Pass类的子类,他们都继承并重写了Pass类中所定义的虚函数。根据需求,我们可以选择继承ModulePass ,CallGraphSCCPass,FunctionPass 或者LoopPass或者RegionPass 等类。通过继承这些父类,我们可以告诉编译系统我们的自定义pass大概要做哪些事情,并且如何去与其他的pass进行组合。
接下来我们尝试写一个简单的pass,从编码,到编译,再到运行,最后讨论如何编写一个高级的pass。
环境设置
下面我们编写一个Hello World pass。我们的pass将实现一个非常简单的功能--打印函数名,这意味着它不会修改源程序,只是简单地打印源程序的相关信息。
首先,配置并构建LLVM项目,然后在LLVM源码文件夹下新建一个目录。遵照官方文档,我们在llvm源码树的lib/Transforms目录下新建一个example目录。
然后将下面的代码添加到lib/Transforms/CMakeLists.txt中
add_subdirectory(example)
这样CMake会将example.cpp文件链接到 ...