【发布时间】:2011-10-01 16:32:17
【问题描述】:
有没有办法使用 BLAS、GSL 或任何其他高性能库进行逐元素向量乘法?
【问题讨论】:
有没有办法使用 BLAS、GSL 或任何其他高性能库进行逐元素向量乘法?
【问题讨论】:
(按字面意思理解问题的标题......)
是的,它可以单独使用 BLAS 完成(尽管它可能不是最有效的方式。)
诀窍是将输入向量之一视为对角矩阵:
⎡a ⎤ ⎡x⎤ ⎡ax⎤
⎢ b ⎥ ⎢y⎥ = ⎢by⎥
⎣ c⎦ ⎣z⎦ ⎣cz⎦
然后您可以使用其中一个矩阵向量乘法函数,该函数可以将对角矩阵作为输入而无需填充,例如SBMV
例子:
void ebeMultiply(const int n, const double *a, const double *x, double *y)
{
extern void dsbmv_(const char *uplo,
const int *n,
const int *k,
const double *alpha,
const double *a,
const int *lda,
const double *x,
const int *incx,
const double *beta,
double *y,
const int *incy);
static const int k = 0; // Just the diagonal; 0 super-diagonal bands
static const double alpha = 1.0;
static const int lda = 1;
static const int incx = 1;
static const double beta = 0.0;
static const int incy = 1;
dsbmv_("L", &n, &k, &alpha, a, &lda, x, &incx, &beta, y, &incy);
}
// Test
#define N 3
static const double a[N] = {1,3,5};
static const double b[N] = {1,10,100};
static double c[N];
int main(int argc, char **argv)
{
ebeMultiply(N, a, b, c);
printf("Result: [%f %f %f]\n", c[0], c[1], c[2]);
return 0;
}
Result: [1.000000 30.000000 500.000000]
【讨论】:
-O2 -fPIC -fstack-protector-strong 选项的 Intel Xeon X7560、OpenBLAS 和 GCC 8.3.0。我的猜测是 ?sbmv 太笼统了,无法充分利用矢量化指令。
我发现 MKL 在它的向量数学函数库 (VML) 中有一整套向量的数学运算,包括 v?Mul,它可以满足我的需求。它适用于 c++ 数组,所以它对我来说比 GSL 更方便。
【讨论】:
总是有 std::valarray1,它定义了在目标支持的情况下经常编译成 SIMD 指令的元素操作(英特尔 C++ /Quse-intel-optimized-headers,G++)。
这两个编译器也会做自动向量化
在这种情况下你可以写
#define N 10000
float a[N], b[N], c[N];
void f1() {
for (int i = 1; i < N; i++)
c[i] = a[i] + b[i];
}
并看到它编译成矢量化代码(例如使用 SSE4)
1 是的,它们很陈旧,通常被认为已经过时,但实际上它们都是标准的,非常适合任务。
【讨论】:
在 GSL 中,gsl_vector_mul 可以解决问题。
【讨论】: