作为针对最近 zenbleed 漏洞 ( https://lock.cmpxchg8b.com/zenbleed.html ) 的缓解措施,建议设置 DE_CFG[9] = 1。
除了LFENCE 在 AMD 处理器上序列化吗?之外,我没有在该 MSR 上找到任何内容。它描述了 DE_CFG[1]。
那么设置DE_CFG[9] = 1会有什么后果呢?
我尝试计算一维离散余弦变换(类型 2),我试图用 numba 提高我的性能。我有以下代码:
import numpy as np
import math
import numba
@numba.jit()
def epsilon(N:int, i: int) -> float:
if i == 0 or i == N:
return math.sqrt(2)/2
return 1.0
@numba.jit()
def dct2(a):
n = len(a)
y = np.empty([2*n])
y[:len(a)] = a
y[n:] = np.flip(a)
fft = np.fft.fft(y)
erg = np.empty([n])
factor = 1/math.sqrt(2*n)
for i in range(0,n):
erg[i] = factor*epsilon(n,i)*(math.cos(-i*2*math.pi/(4*n))*fft[i].real - math.sin(-i*2*math.pi/(4*n))*fft[i].imag)
return erg
Run Code Online (Sandbox Code Playgroud)
我认为它无法编译for循环,但我不知道为什么。根据我对 numba 文档的理解,应该能够解除循环。
我收到以下警告:
In definition 0:
All templates rejected with literals.
In definition …Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
double x(double a,double b) {
return a*(float)b;
}
Run Code Online (Sandbox Code Playgroud)
它做了一个转换形式double,float然后再double乘以。
当我gcc 9.1用-O3on编译它时,x86/64我得到:
x(double, double):
movapd xmm2, xmm0
pxor xmm0, xmm0
cvtsd2ss xmm1, xmm1
cvtss2sd xmm0, xmm1
mulsd xmm0, xmm2
ret
Run Code Online (Sandbox Code Playgroud)
使用clang和旧版本的gcc我得到这个:
x(double, double):
cvtsd2ss xmm1, xmm1
cvtss2sd xmm1, xmm1
mulsd xmm0, xmm1
ret
Run Code Online (Sandbox Code Playgroud)
在这里我不抄xmm0成xmm2,这似乎不需要我。
随着gcc 9.1和-Os我得到:
x(double, double):
movapd xmm2, xmm0
cvtsd2ss xmm1, xmm1
cvtss2sd xmm0, …Run Code Online (Sandbox Code Playgroud) 我想将迭代器传递给一个函数,然后该函数从这些迭代器中计算一些值。我不确定这样一个函数的健壮签名会是什么样子。假设我想迭代 f64。您可以在操场上找到代码:https://play.rust-lang.org/?version =stable&mode=debug&edition=2018&gist=c614429c541f337adb102c14518cf39e
我的第一次尝试是
fn dot(a : impl std::iter::Iterator<Item = f64>,b : impl std::iter::Iterator<Item = f64>) -> f64 {
a.zip(b).map(|(x,y)| x*y).sum()
}
Run Code Online (Sandbox Code Playgroud)
如果我们尝试迭代切片,则编译失败
所以你可以做
fn dot<'a>(a : impl std::iter::Iterator<Item = &'a f64>,b : impl std::iter::Iterator<Item = &'a f64>) -> f64 {
a.zip(b).map(|(x,y)| x*y).sum()
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试迭代映射的范围,则无法编译。(为什么编译器在这里需要livetime参数?)
所以我尝试接受参考文献,而不是一般的参考文献:
pub fn dot<T : Borrow<f64>, U : Borrow<f64>>(a : impl std::iter::Iterator::<Item = T>, b: impl std::iter::Iterator::<Item = U>) -> f64 {
a.zip(b).map(|(x,y)| x.borrow()*y.borrow()).sum()
}
Run Code Online (Sandbox Code Playgroud)
这适用于我尝试过的所有组合,但它非常冗长,我并不真正理解它的每个方面。
还有更多案例吗?
解决这个问题的最佳实践是什么?
让我们考虑一个简单的简化,例如点积:
pub fn add(a:&[f32], b:&[f32]) -> f32 {
a.iter().zip(b.iter()).fold(0.0, |c,(x,y)| c+x*y))
}
Run Code Online (Sandbox Code Playgroud)
使用 rustc 1.68 与-C opt-level=3 -C target-feature=+avx2,+fma
我得到
.LBB0_5:
vmovss xmm1, dword ptr [rdi + 4*rsi]
vmulss xmm1, xmm1, dword ptr [rdx + 4*rsi]
vmovss xmm2, dword ptr [rdi + 4*rsi + 4]
vaddss xmm0, xmm0, xmm1
vmulss xmm1, xmm2, dword ptr [rdx + 4*rsi + 4]
vaddss xmm0, xmm0, xmm1
vmovss xmm1, dword ptr [rdi + 4*rsi + 8]
vmulss xmm1, xmm1, dword ptr [rdx + …Run Code Online (Sandbox Code Playgroud) 像这样展平数组对于构建原始类型安全吗?
let a = [[0u32;4];4];
let b = std::mem::transmute::<[[u32;4];4], [u32; 16]>(a);
Run Code Online (Sandbox Code Playgroud)
在什么条件下这是安全的?
考虑以下代码
std::vector<std::array<double,10>> a(10);
Run Code Online (Sandbox Code Playgroud)
如果我正确理解标准a将不会被零初始化,因为 std::vector 构造函数上的 en.cppreference.com 说
- 使用 count 个默认插入的 T 实例构造容器。不制作副本。
所以因为默认初始化std::array<double, 10>不会用零填充它,a也不会包含零。
这是真的?
如何强制执行零初始化?
会a.data()指向100个连续double值吗?
编辑:
这是godbolt在gcc 10.2上使用-O2的输出
main:
mov edi, 800
sub rsp, 8
call operator new(unsigned long)
mov rdi, rax
lea rdx, [rax+800]
.L2:
mov QWORD PTR [rax], 0x000000000
add rax, 80
mov QWORD PTR [rax-72], 0x000000000
mov QWORD PTR [rax-64], 0x000000000
mov QWORD PTR [rax-56], 0x000000000
mov QWORD PTR [rax-48], 0x000000000
mov QWORD PTR …Run Code Online (Sandbox Code Playgroud)