在两种不同的处理器架构上期望 LAPACK 例程的结果相同是否合理?
Is it reasonable to expect identical results for LAPACK routines on two different processor architectures?
我正在尝试使用 Apple Accelerate 库通过 LAPACK 反转 400x400 矩阵。我使用 ?getrf_
和 ?getri
.
创建了一个矩阵求逆方法
void invert() {
aligned_buffer<int> pivot(get_num_rows()*get_num_columns());
int info = 0;
int num_rows = get_num_rows();
int num_columns = get_num_columns();
if constexpr (std::is_same<T, float>::value) {
sgetrf_(&num_rows, &num_columns, const_cast<T *> (get()),
&num_rows, pivot.data(), &info);
} else {
dgetrf_(&num_rows, &num_columns, const_cast<T *> (get()),
&num_rows, pivot.data(), &info);
}
assert((info == 0) && "Error factorizing matrix.");
aligned_buffer<T> work(work_size);
if constexpr (std::is_same<T, float>::value) {
sgetri_(&num_rows, const_cast<T *> (get()), &num_rows,
pivot.data(), work.data(), &work_size, &info);
} else {
dgetri_(&num_rows, const_cast<T *> (get()), &num_rows,
pivot.data(), work.data(), &work_size, &info);
}
assert((info == 0) && "Error inverting matrix.");
}
但是,当 运行 两台不同机器上的代码时,我似乎得到了不同的结果。一台机器有四核英特尔酷睿 i7,另一台机器有四核英特尔酷睿 i5。当我比较倒矩阵的结果时,除了第 49,50 97,98、148,149 197,198 行等之外,结果是相同的。差异很小但仍然存在。
对于使用相同的 LAPACK 库或不同的 lapack 库的两种不同的处理器架构,期望这些精度水平与此级别相同是合理的吗?
一般来说,不,在不同的硬件上期望相同的位精确结果是不合理的。您正在执行数值不稳定的程序这一事实也可能导致存在的任何差异被放大(如果可能的话,通常更喜欢用因子求解而不是求逆)。
由于浮点运算的性质,运算顺序或精度的任何差异都可能导致不同的结果。 BLAS(它是大部分 LAPACK 的基础)通常主要是为了性能而编写的。这意味着对于不同的微架构,更不用说不同的架构,操作顺序可能不同(例如,为了在核心中容纳不同数量的 FMA 单元)。由于某些操作的循环剥离,数据对齐也会产生影响。 FMA 的可用性、向量长度、and/or 不同的内部精度也会产生影响。
即使在相同的硬件上,使用相同的库,以相同的对齐方式使用相同的数据,如果涉及线程,您仍然可能无法获得可重复性,除非库作者已经竭尽全力保证这一点。
我正在尝试使用 Apple Accelerate 库通过 LAPACK 反转 400x400 矩阵。我使用 ?getrf_
和 ?getri
.
void invert() {
aligned_buffer<int> pivot(get_num_rows()*get_num_columns());
int info = 0;
int num_rows = get_num_rows();
int num_columns = get_num_columns();
if constexpr (std::is_same<T, float>::value) {
sgetrf_(&num_rows, &num_columns, const_cast<T *> (get()),
&num_rows, pivot.data(), &info);
} else {
dgetrf_(&num_rows, &num_columns, const_cast<T *> (get()),
&num_rows, pivot.data(), &info);
}
assert((info == 0) && "Error factorizing matrix.");
aligned_buffer<T> work(work_size);
if constexpr (std::is_same<T, float>::value) {
sgetri_(&num_rows, const_cast<T *> (get()), &num_rows,
pivot.data(), work.data(), &work_size, &info);
} else {
dgetri_(&num_rows, const_cast<T *> (get()), &num_rows,
pivot.data(), work.data(), &work_size, &info);
}
assert((info == 0) && "Error inverting matrix.");
}
但是,当 运行 两台不同机器上的代码时,我似乎得到了不同的结果。一台机器有四核英特尔酷睿 i7,另一台机器有四核英特尔酷睿 i5。当我比较倒矩阵的结果时,除了第 49,50 97,98、148,149 197,198 行等之外,结果是相同的。差异很小但仍然存在。
对于使用相同的 LAPACK 库或不同的 lapack 库的两种不同的处理器架构,期望这些精度水平与此级别相同是合理的吗?
一般来说,不,在不同的硬件上期望相同的位精确结果是不合理的。您正在执行数值不稳定的程序这一事实也可能导致存在的任何差异被放大(如果可能的话,通常更喜欢用因子求解而不是求逆)。
由于浮点运算的性质,运算顺序或精度的任何差异都可能导致不同的结果。 BLAS(它是大部分 LAPACK 的基础)通常主要是为了性能而编写的。这意味着对于不同的微架构,更不用说不同的架构,操作顺序可能不同(例如,为了在核心中容纳不同数量的 FMA 单元)。由于某些操作的循环剥离,数据对齐也会产生影响。 FMA 的可用性、向量长度、and/or 不同的内部精度也会产生影响。
即使在相同的硬件上,使用相同的库,以相同的对齐方式使用相同的数据,如果涉及线程,您仍然可能无法获得可重复性,除非库作者已经竭尽全力保证这一点。