Rust 的定位是和 C/C++ 一样运行效率高、没有垃圾回收,同时避免了 C/C++ 的很多错误,例如访问已释放的内存。
result 的 key 指向 sentence 的子字符串,所以 result 的生命周期应该不长于 sentence 。
否则先释放 sentence ,再访问 result ,就访问了已释放的内存,而这部分内存可能已经写入了其它数据。
C/C++ 这样做的话,可以通过编译,但运行时可能会出现莫名其妙的错误。
Rust 通过生命周期检查,可以避免这种错误。
'''
use std::collections::HashMap;
fn index_t_words<'a>(sentence: &'a String, bias: &str) -> HashMap<&'a str, usize> {
let mut result: HashMap<&str, usize> = HashMap::new();
for (idx, word) in sentence.split(' ').enumerate() {
if word.chars().nth(0).unwrap() == 't' {
result.insert(word, idx);
}
};
result
}
fn main() {
{
// 正确
let sentence: String = String::from("magic happens in the test statement");
let bias: String = String::from("spoiler");
let result = index_t_words(&sentence, &bias);
println!("{:?}", result);
}
{
// 错误,sentence 已经提前释放
let result = {
let sentence: String = String::from("magic happens in the test statement");
let bias: String = String::from("spoiler");
index_t_words(&sentence, &bias)
};
println!("{:?}", result);
}
}
'''
result 的 key 指向 sentence 的子字符串,所以 result 的生命周期不长于 sentence 。
result 的生命周期与 bias 无关,无脑加 'a 是有问题的,例如:
'''
use std::collections::HashMap;
fn index_t_words<'a>(sentence: &'a String, bias: &'a str) -> HashMap<&'a str, usize> {
let mut result: HashMap<&str, usize> = HashMap::new();
for (idx, word) in sentence.split(' ').enumerate() {
if word.chars().nth(0).unwrap() == 't' {
result.insert(word, idx);
}
};
result
}
fn main() {
let sentence: String = String::from("magic happens in the test statement");
let result = {
let bias: String = String::from("spoiler");
index_t_words(&sentence, &bias) // 错误!
};
println!("{:?}", result);
}
'''
正确的做法是:
'''
use std::collections::HashMap;
fn index_t_words<'a>(sentence: &'a String, bias: &str) -> HashMap<&'a str, usize> {
let mut result: HashMap<&str, usize> = HashMap::new();
for (idx, word) in sentence.split(' ').enumerate() {
if word.chars().nth(0).unwrap() == 't' {
result.insert(word, idx);
}
};
result
}
fn main() {
let sentence: String = String::from("magic happens in the test statement");
let result = {
let bias: String = String::from("spoiler");
index_t_words(&sentence, &bias)
};
println!("{:?}", result);
}
'''
只有一个参数时可以省略生命周期标注。
如果没有搞懂所有权、借用、生命周期这些概念,那还处于开始特别难的阶段。
可以试试牛顿法,用一阶二阶差分代替微分,一定条件下收敛。
或者每次迭代从一点及附近两点作一条二次曲线(抛物线),直接移动的极值点。
BFGS 是用一系列点的梯度得到类海森矩阵的逆,可以尝试退化到一元函数的情况。
另外黄金分割法每计算一个点区间缩小 0.618 倍,理论上效率比三分、四分法高。
jupyter notebook 可以输出 HTML ,所以格式化文本、数学公式、表格、图片、3d 、交互式等都不是问题。
mathematica 不光可以输出这些,输入也可以是数学公式、图片等。
BFGS 算法是求多元函数极值的。
牛顿法需要二阶导数。
这个可以直接用黄金分割法,也就是 0.618 法,不断缩小区间,收敛速度是指数级的。
nvidia-smi 命令可以查看 GPU 的状态,包括显存、计算力。
占用显存高不代表占用计算力,和内存和 CPU 占用一个道理。