- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这个问题在这里已经有了答案:
Why is my Rust program slower than the equivalent Java program?
(1 个回答)
1年前关闭。
我移植了一个 Java 类,该类循环遍历从 n 个选项中选择 k 个元素到 Rust 的所有可能的无序组合,期望 Rust 能帮助我加快计算速度。但是当两者并驾齐驱时,Java 的速度几乎快了两倍!
因为这对我来说根本不合适,而且我刚刚开始使用 Rust,我一定做错了什么,并且想知道是否有更多 Rust 经验的人会帮助我弄清楚为什么我的 Rust 代码要慢得多。
这是我的通用接口(interface)、实现和测试代码的 Java 代码:
public interface Choice<Type> {
/**
* Returns the number of possible options that this choice provides.
*
* @return the number of choices
*/
public long getChoices();
/**
* Returns the choice with the given index.
*
* @param index - the index of the choice to return
* @return the choice of the given index
*/
public Type getChoice(long index);
}
public class NChooseK implements Choice<int[]> {
private final int n;
private final int k;
private final long count;
public NChooseK(int n, int k) {
if ((n<=0) || (k<0) || (k>n)) throw new IllegalArgumentException();
this.n = n;
this.k = k;
this.count = choose(n, k);
}
@Override
public long getChoices() {
return count;
}
@Override
public int[] getChoice(long m) {
if (k==0) return new int[0];
long count = this.count;
int[] result = new int[this.k];
int n = this.n;
int k = this.k;
long x = (count-1) - m;
while (true) {
if (n == k) {
while (true) {
result[this.k - k] = this.n - k;
if (k==1) return result;
k--;
}
}
count = count * (n-k) / n;
if (x >= count) {
result[this.k - k] = this.n - n;
if (k==1) return result;
x -= count;
count = count * k / (n-k);
k--;
}
n--;
}
}
private long choose(int n, int k) {
if (n<k) return 0;
if (k>n-k) k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b = b*m/i;
return b;
}
}
public class Test {
public static void main(String[] args) {
NChooseK nck = new NChooseK(26, 13);
long choices = nck.getChoices();
System.out.println("Running ("+choices+" choices)...");
long start = System.currentTimeMillis();
for (long index = 0; index<choices; index++) {
int[] choice = nck.getChoice(index);
//System.out.println(ArrayTools.toString(choice));
}
long end = System.currentTimeMillis();
System.out.println("Done ("+((end - start)/1000.0)+"s)!");
}
}
这是我认为最接近 Rust 的翻译:
pub trait Choice<Type> {
/// Returns the number of possibilities for this choice.
fn get_choices(&self) -> u32;
/// Returns the posibility of the given index.
fn get_choice(&self, index: u32) -> Type;
}
use super::choice::Choice;
pub struct NChooseK {
n: u32,
k: u32,
count: u32,
}
impl NChooseK {
pub fn new(n: u32, k: u32) -> Result<NChooseK, &'static str> {
if k > n {
Err("invalid parameters: k cannot be larger than n")
} else {
Ok(NChooseK {
n: n,
k: k,
count: choose(n, k).unwrap() as u32,
})
}
}
}
impl<'a> Choice<Vec<u32>> for NChooseK {
fn get_choices(&self) -> u32 {
self.count
}
fn get_choice(&self, m: u32) -> Vec<u32> {
if self.k == 0 {
return vec![];
}
let mut count = self.count;
let mut result:Vec<u32> = Vec::with_capacity(self.k as usize);
let mut n = self.n;
let mut k = self.k;
let mut x = (count-1) - m;
loop {
if n == k {
loop {
result.push(self.n - k);
if k == 1 {
return result;
}
k -= 1;
}
}
count = count * (n - k) / n;
if x >= count {
result.push(self.n - n);
if k == 1 {
return result;
}
x -= count;
count = count * k / (n - k);
k -= 1;
}
n -= 1;
}
}
}
fn choose(n: u32, mut k: u32) -> Option<u64> {
if k > n-k {
k = n-k;
}
let mut b : u64 = 1;
let mut m = n;
for i in 1..=k {
if b > 0xFFFFFFFFFFFFFFFF / (m as u64) {
return None;
}
b = b * (m as u64) / (i as u64);
m -= 1;
}
Some(b)
}
fn main() {
let nck = NChooseK::new(26, 13).unwrap();
let choices = nck.get_choices();
println!("Running ({} choices)...", choices);
let start = time::precise_time_s();
for index in 0..choices {
let choice = nck.get_choice(index);
//println!("{:?}", choice);
}
let end = time::precise_time_s();
println!("Done ({}s)!", end - start);
}
Rust 代码需要大约 12 到 12.5 秒来运行约 1000 万次 get_choice 调用,而 Java 代码需要 6.5 到 7 秒! WTF?!?!?
result.push(...)
语句将运行时间降低到 9 到 9.5 秒。这是一个很大的区别(比我预期的要大!),但仍然比 Java 慢! NChooseK(7, 3)
),两个版本都会产生相同的精确输出值(ArrayTools.toString(...)
只是一个简单的辅助函数,它连接用逗号将 int 数组的组件转换为字符串;决定将其省略,因为这里已经有很多代码)最佳答案
始终使用 cargo build --release
或 cargo run --release
拥有rustc
/llvm
当您尝试压缩性能时优化您的代码:
$ cargo build 2>/dev/null && time cargo -q run 2>/dev/null
Running (10400600 choices)...
Done (9.487796306610107s)!
real 0m9,512s
user 0m9,500s
sys 0m0,000s
$ cargo build --release 2>/dev/null && time cargo -q run --release 2>/dev/null
Running (10400600 choices)...
Done (3.2046568393707275s)!
real 0m3,229s
user 0m3,222s
sys 0m0,008s
关于Java 的速度几乎是 Rust 的两倍?!?我错过了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63370456/
我正在用 C 写一个高级计算器。正如你所猜到的,它目前有很多函数,我使用一个开关来对每个函数名进行适当的操作。它是这样的: switch(hash_of(function_name_currently
在大约四天的时间里,我一直在收集托管应用程序的性能计数器。在此期间,发生了以下垃圾回收: 第 0 代:133,695 第一代:133,413 第 2 代:133,254 其中一些是使用GC.Colle
我构建了这个: [ Workshop_templates 表 ] id_template | Workshop_name 1 | Conflict resolution 2 | Building tr
我有一个 N 的列表元素,我想抽样 M ( N/2 . IE。当超过一半的值被采样时。但它非常适合 M N/2 时反转问题。 : 注意:这实际上是创建一个大小为 N 的屏蔽列表对于 M 是 Fals
伙计们,我是竞争性编程的新手,我遇到了一个小问题在提供输入的同时在问题中,顶点数从 1 到 n但是我编写程序时考虑到节点是从 0 开始的 但是当我通过从每个边的每个顶点减少 1 来输入测试用例时,我的
在一次旅行中,有多个停靠点,(一个停靠点 = 一个或多个订单加载或交付的地址),按特定顺序排列。 例如: Trip A Trip_order Action Place Ord
我有一个关于由微服务组成的应用程序架构的问题。 我的微服务很少,但在这个问题的上下文中有趣的是: 人力资源 - 这里存储了所有用户数据,如用户名、性别、用户体验等。 工作机会 - 这里存储了每个招聘广
假设我的工作空间(全局环境)中有许多对象,并且我想将大多数对象存储在列表中。这是一个简化的示例: # Put some objects in the workspace A <- 1 B <- 2 C
当我获得与本地时间相同的时间戳时,firebase 生成的服务器时间戳是否会自动转换为本地时间,或者我错过了什么? _firestore.collection("9213903123").docume
我需要帮助才能将未知整数分成给定数量的偶数部分——或者至少尽可能地均匀。各部分之和应为原值,但各部分应为整数,且应尽可能接近。 参数 num: Integer - 应该被分成相等部分的数字 parts
我的 Java 程序中有一个带有 JPanel 的 ScrollPane,它附加了大量文本。我需要 ScrollPane 在每次添加后滚动到最底部。我对以下代码的问题是它“几乎”滚动到底部但不是一直滚
我想检查两个稀疏数组是否(几乎)相等。而对于 numpy 数组,你可以这样做: import numpy as np a = np.ones(200) np.testing.assert_array_
我有以下一组几乎相同的 each 语句。我需要添加大约 20 个遵循类似模式的内容。我正在尝试找出如何获取小变量并将它们更新为单个语句(而不是 20 次相同但略有不同的内容)。 $.each(main
所以我想获取两个字典中(几乎)匹配的键的值并将它们连接起来。我尝试过: dict3 = {key:dict1[key].strip() for key in dict2.keys() if key.p
我的表看起来像这样: | id (int) | sentence (varchar) | 我想找到除了一个特定单词之外几乎相同的所有行。例如: | 230 | test | | 321 | test
起始情况:MS SQL 中有一个现有的数据库模式,它与 MySQL 中的现有模式完全相同(数据库优先 - 无法更改,因为已广泛安装)。但是,它们在用于相应列的数据类型方面可能略有不同。该数据库系统必须
对于复杂的元素,一个很好的做法是(几乎)总是在闭包中定义 Polymer 以保持所有只应在内部修改的变量和方法私有(private),而不是将它们附加到元素(例如 'this ')? 喜欢以下内容:
我正在解析 Java 中的 RestAssured 调用,该调用返回对象列表。如果我使用此代码,Idea 会生成未经检查的分配警告: List availableInventories = ListP
我真的被难住了。我所拥有的是一个样式化为矩形的 div,其中包含作为页面主要标题的文本。相关代码如下: HTML: SIN CSS: h1 { text-align:right
我需要将单选按钮及其旁边的文本包装在标签中,只是为了更加用户友好。 几天前我遇到了类似的问题,我有一个复选框,并且在我有一个 span 元素之后立即出现。我可以包装这两个元素。 我有这个 HTML:
我是一名优秀的程序员,十分优秀!