小编Sta*_*eur的帖子

为什么-march = native很少使用?

对于大多数C/C++编译器,有一个可传递给编译器的标志-march=native,它告诉编译器调整生成的代码以用于主机CPU的微架构和ISA扩展.即使它没有使用相同的名称,通常也有基于LLVM的编译器的等效选项,例如rustc或swiftc.

根据我自己的经验,这个标志可以为数字密集型代码提供大量的加速,而且听起来它可以免于为你自己的机器编译的代码的妥协.也就是说,我认为我没有看到任何默认启用它的构建系统或静态编译器:

  • 显然,任何要求您传递它的命令行编译器可执行文件都不会默认使用它.

  • 我想不出任何默认启用它的IDE.

  • 我想不出任何共同构建系统我已经与(工作的cmake,automake,cargo,spm,等),使其能够在默认情况下,即使是最优化的基础之上.

我可以想到一些原因,但没有一个真的令人满意:

  • 使用-march=native不适合将分发给其他计算机的二进制文件.也就是说,我发现自己为自己的机器编译源代码比其他机器更频繁,这并不能解释它在调试版本中的缺乏用途,因为它没有分发的意图.

  • 至少在Intel x86 CPU上,我的理解是不经常使用AVX指令会降低性能或功率效率,因为AVX单元在不使用时断电,要求它上电以供使用,以及许多Intel CPU下行运行AVX指令.尽管如此,它只解释了为什么不启用AVX,而不是为什么代码不会针对特定微架构处理常规指令而调整.

  • 由于大多数x86 CPU使用具有寄存器重命名的花哨的无序超标量流水线,因此针对特定微架构的调优代码可能并不是特别重要.不过,如果它可以帮助,为什么不使用它呢?

gcc clang compiler-optimization

21
推荐指数
3
解决办法
3691
查看次数

如何在 Rust 中断言 io 错误?

有很多教程展示了如何在 Rust 中编写单元测试。我读过十几本书,所有这些都侧重于在成功的情况下维护价值观。对于error. PartialEq默认情况下,错误不会实现特征,因此您不能使用assert_eq!宏。此外,根据发生的问题类型(例如io::Error,可能是不同类型的),某些函数可能会返回多个错误变体。我可以检查是否发生了错误,但这似乎还不够。

下面举例。

fn parse_data(input: i32) -> Result<i32, io::Error> {
    match input {
        0 => Ok(0),
        _ => Err(io::Error::new(io::ErrorKind::InvalidData, "unexpected number"))
    }
}

#[test]
fn test_parsing_wrong_data() {
    let result = parse_data(1);
    assert!(result.is_err());
    let got = result.unwrap_err();
    let want = io::Error::new(io::ErrorKind::InvalidData, "unexpected number");

    // compilation error here: binary operation `==` cannot be applied to type `std::io::Error`
    assert_eq!(want, got);
}
Run Code Online (Sandbox Code Playgroud)

我认为这不是惯用的方法,因为它没有编译。因此,问题是 - 在类似情况下,什么是适当且惯用的方法?

error-handling unit-testing rust

21
推荐指数
3
解决办法
1万
查看次数

将 Vec&lt;u64&gt; 转为 Vec&lt;(&amp;str, u64)&gt; 用于 tui::BarChart 数据

我怎样才能把 aVec<u64>变成 a Vec<(&str, u64)>,使得前者的索引嵌入到str后者的部分中?

例如,[4, 9, 3]应该变成[("0", 4), ("1", 9), ("2", 3)].

我想这样做的原因是因为我想使用来自 TUI 的条形图绘制我的向量的条形图,这需要类似的类型。

我尝试了一些明显的事情,例如循环和推送:

fn main() {
    let my_vec: Vec<u64> = vec![4, 9, 3];
    let mut result: Vec<(&str, u64)> = Vec::new();
    for (k, v) in my_vec.iter().enumerate() {
        result.push((&k.to_string(), *v));
    }

    assert_eq!(result, [("0", 4), ("1", 9), ("2", 3)]);
}
Run Code Online (Sandbox Code Playgroud)
error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:5:23
  |
5 |         result.push((&k.to_string(), *v));
  |                       ^^^^^^^^^^^^^      - …
Run Code Online (Sandbox Code Playgroud)

rust

17
推荐指数
2
解决办法
326
查看次数

使用`NULL`指针转换说明符`p`的行为是什么?

我想知道是否:

void *ptr = NULL;
printf("%p\n", ptr);
Run Code Online (Sandbox Code Playgroud)

会不会给出(nil)输出?

它是依赖于标准库实现,还是C99标准规范?

c null printf

12
推荐指数
2
解决办法
5394
查看次数

通过C函数调用抛出C++异常

我有三个免费功能:F0,F1和F2.F0调用F1,然后调用F2.

F0和F2是C++函数,其中F1是C函数.F2通过以下方式暴露于F1:extern"C"

每个免费功能的代码如下:

~~~~ F0.cpp ~~~~

void f0()
{
   try
   {
      f1();
   }
   catch (...)
   {}
}

~~~~ F0.cpp ~~~~


~~~~ F1.c ~~~~

void f1()
{
   f2();
}

~~~~ F1.c ~~~~


~~~~ F2.cpp ~~~~

void f2()
{
  throw 1
}

~~~~ F2.cpp ~~~~
Run Code Online (Sandbox Code Playgroud)

题:

是否例外F2抛出的进展,通过F1和F0正确抓到?

或者由于未处理异常而调用std :: unexpected,或者整个事情应该是未定义的行为? - 如果是这样,它在标准中的哪个部分讨论了在这个特定环境中的异常处理.


请注意,这不是关于在C中处理异常,而是在异常可以流经C层(如果有的话)并被调用C++层捕获的情况下发生的情况 - 以及任何产生的副作用等.

c c++ exception function undefined-behavior

12
推荐指数
1
解决办法
558
查看次数

使用 serde 实现两种(反)序列化格式

我已经成功地用于serde_json反序列化和序列化 JSON。我的设置看起来有点像这样(非常简单):

use serde::{Deserialize, Serialize};
use serde_json;
use serde_with::skip_serializing_none;

#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Foo {
    #[serde(flatten)]
    bar: Option<Bar>,
    
    baz_quux: Option<u8>,
}

#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
struct Bar {
    #[serde(rename = "plughXyzzySomeRandomStuff")]
    plugh_xyzzy: Option<u8>
}
Run Code Online (Sandbox Code Playgroud)

然后我实现了FromStrand Displayon Foo,它依次调用serde_json::from_str和serde_json::to_string,以轻松(反)序列化该结构。

但是,我现在还想支持serde_ini将 INI 文件序列化(反序列化)到相同的 Rust 数据结构。但我真的不知道该怎么做。

结构本身很简单,但我的具体问题在于属性:

  • 这些键在 JSON 和 INI 格式中的命名方式不同(JSON 格式使用惯用的驼峰命名法,而 INI 则没有),因此我必须以其他方式解决#[serde(rename)]和#[serde(rename_all)]属性,但我不确定在哪里或如何解决。
  • #[serde(flatten)] 似乎不适用于的serde_ini全字符串值,它需要#[serde(deserialize_with="from_str)]"所有非字符串值的属性,但这显然只适用于 INI 值,而不适用于 JSON 值。 …

rust serde

12
推荐指数
1
解决办法
2813
查看次数

将void*作为函数调用而不声明函数指针

我已经搜索过但找不到任何结果(我的术语可能已关闭)所以请原谅我,如果以前曾经问过这个问题.

我想知道是否有一种简单的方法可以void*在不首先声明函数指针然后为函数指针分配地址的情况下调用C中的函数.

即.假设要调用的函数是typevoid(void)

void *ptr;
ptr = <some address>;
((void*())ptr)(); /* call ptr as function here */
Run Code Online (Sandbox Code Playgroud)

用上面的代码,我得到错误C2066:在VC2008中强制转换为函数类型是非法的

如果可能,具有返回类型和多个参数的函数的语法有何不同?

c pointers function void

11
推荐指数
3
解决办法
1万
查看次数

我*不*想要函数exp的正确舍入

Debian系统上的C数学库的GCC实现显然符合(IEEE 754-2008)函数的实现,这意味着舍入应始终是正确的:exp

(来自维基百科)IEEE浮点标准保证加,减,乘,除,融合乘加,平方根和浮点余数将给出无限精度运算的正确舍入结果.对于更复杂的功能,1985年标准中没有给出这样的保证,它们通常只能在最后一点内准确到达.但是,2008标准保证符合要求的实现将给出正确的舍入结果,这些结果遵循主动舍入模式; 但是,函数的实现是可选的.

事实证明,我遇到了这个功能实际上阻碍的情况,因为exp函数的确切结果通常几乎恰好处于两个连续double值(1)之间的中间位置,然后程序进行了大量的进一步计算,失去了速度高达400(!):这实际上是对我的解释(不好问:-S)问题#43530011.

(1)更确切地说,当参数exp变为(2 k + 1)×2 -53,其中k为相当小的整数(例如242)时,就会发生这种情况.特别是,所涉及的计算pow (1. + x, 0.5)倾向于exp使用这样的参数进行调用x,其数量级为2 -44.

由于正确舍入的实现在某些情况下可能非常耗时,我想开发人员也会设计一种方法来获得稍微不那么精确的结果(例如,最多只有0.6 ULP或类似的东西)对于给定范围内的每个参数值(大致)有界限...(2)

......但是怎么做?

(2)我的意思是,我只是不希望像(2 k + 1)×2 -53这样的参数的某些特殊值比相同数量级的大多数值更耗时; 但是我当然不介意参数的某些特殊值是否更快,或者如果大参数(绝对值)需要更大的计算时间.

这是一个显示现象的最小程序:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>

int main (void)
 {
  int i;
  double a, c;
  c = 0;
  clock_t start = clock …
Run Code Online (Sandbox Code Playgroud)

c rounding ieee-754 exp libm

11
推荐指数
1
解决办法
330
查看次数

如何将一组对象传递给WebAssembly并将其转换为带有wasm-bindgen的结构向量?

可以像这样传递一个整数数组:

const js = import("./webassembly_rust");
let array_nums = [1,2,3,4,5,6,7,8,9];

js.then(js => {
  js.test( array_nums );
}); 
Run Code Online (Sandbox Code Playgroud)

到WebAssembly并将其保存在这样的向量中:

extern crate serde_json;
extern crate wasm_bindgen;

use wasm_bindgen::prelude::*;

#[macro_use]
extern crate serde_derive;

#[wasm_bindgen]
pub fn test(array: JsValue) {
    let elements: Vec<u32> = array.into_serde().unwrap();
}
Run Code Online (Sandbox Code Playgroud)

也可以像这样传递一个对象:

const js = import("./webassembly_rust");
let jsObject = {name: "hello world", id: "99", parent_id: "11"};

js.then(js => {
  js.test( jsObject );
}); 
Run Code Online (Sandbox Code Playgroud)

到WebAssembly并将其保存为这样的Element结构:

extern crate serde_json;
extern crate wasm_bindgen;

use wasm_bindgen::prelude::*;

#[macro_use]
extern crate serde_derive;

#[derive(Serialize, Deserialize)] …
Run Code Online (Sandbox Code Playgroud)

rust webassembly serde wasm-bindgen

11
推荐指数
1
解决办法
1709
查看次数

为什么将`ptr :: write`与MaybeUninit`s的数组一起使用?

在标准库中,文档显示了如何实例化MaybeUninits的数组 :

let arr: [MaybeUninit<T>; N] =
    MaybeUninit::uninit().assume_init();
Run Code Online (Sandbox Code Playgroud)

我们知道这是安全的,因为的合同MaybeUninit允许使用未初始化的值。接下来,我们被要求ptr::write(value)用来初始化每个元素。但这unsafe又需要代码。我们还知道覆盖a MaybeUninit是安全的,因为它没有drop任何作用。那么,为什么不覆盖它arr[i] = MaybeUninit::new(value)呢?

initialization rust

11
推荐指数
1
解决办法
205
查看次数