【发布时间】:2021-08-18 01:18:26
【问题描述】:
我正在尝试优化以下简化的 ReLU 模拟代码。该代码使用三元运算,这可能会妨碍编译器的自动矢量化。如何矢量化这段代码?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mkl.h>
void relu(double* &Amem, double* Z_curr, int bo)
{
for (int i=0; i<bo; ++i) {
Amem[i] = Z_curr[i] > 0 ? Z_curr[i] : Z_curr[i]*0.1;
}
}
int main()
{
int i, j;
int batch_size = 16384;
int output_dim = 21;
// double* Amem = new double[batch_size*output_dim];
// double* Z_curr = new double[batch_size*output_dim];
double* Amem = (double *)mkl_malloc(batch_size*output_dim*sizeof( double ), 64 );
double* Z_curr = (double *)mkl_malloc(batch_size*output_dim*sizeof( double ), 64 );
memset(Amem, 0, sizeof(double)*batch_size*output_dim);
for (i=0; i<batch_size*output_dim; ++i) {
Z_curr[i] = -1+2*((double)rand())/RAND_MAX;
}
relu(Amem, Z_curr, batch_size*output_dim);
}
要编译它,如果您有 MKL,则使用以下内容,否则使用普通 g++ -O3。
g++ -O3 ex.cxx -L${MKLROOT}/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -liomp5
到目前为止,我已尝试将 -march=skylake-avx512 添加为编译器选项,但它并没有像我使用选项 -fopt-info-vec-all 进行编译时发现的那样对循环进行矢量化:
ex.cxx:9:16: missed: couldn't vectorize loop
ex.cxx:9:16: missed: not vectorized: control flow in loop.
ex.cxx:6:6: note: vectorized 0 loops in function.
ex.cxx:9:16: missed: couldn't vectorize loop
ex.cxx:9:16: missed: not vectorized: control flow in loop.
这是我目前花费的时间:
time ./a.out
real 0m0.034s
user 0m0.026s
sys 0m0.009s
【问题讨论】:
-
在什么情况下
Z_curr[i] ? Z_curr[i] : Z_curr[i]*0.1与Z_curr[i]不同? -
其实应该是
Z_curr[i] > 0 ? Z_curr[i] : Z_curr[i]*0.1;我正在纠正。 -
如果我做
Amem[i] = Z_curr[i] * (std::copysign(0.45, Z_curr[i]) + 0.55);,它确实会做一些矢量化,除非你依赖有符号零或NaN行为,否则它应该是等价的。 -
@Ruslan 更简单的是
max(Z_curr[i], 0.1*Z_curr[i])(甚至应该适用于无穷大或NaN)
标签: c vectorization conditional-operator