好几次,我在matlab,fortran ......中遇到过这个术语......但是我从来没有找到解释是什么意思,它有什么作用?所以我在这里问,什么是矢量化,例如,"循环是矢量化的"是什么意思?
我正在寻找有关如何与SSE进行并行前缀和的一些建议.我有兴趣在一系列整数,浮点数或双精度数上执行此操作.
我想出了两个解决方案.一个特例和一般情况.在这两种情况下,解决方案在与OpenMP并行的两次传递中在阵列上运行.对于特殊情况,我在两次传球时使用SSE.对于一般情况,我只在第二遍使用它.
我的主要问题是如何在一般案例的第一遍中使用SSE? 以下链接simd-prefix-sum-on-intel-cpu显示字节的改进,但不是32位数据类型.
特殊情况称为特殊情况的原因是它要求数组采用特殊格式.例如,假设a浮点数组中只有16个元素.然后,如果数组像这样重新排列(结构数组结构):
a[0] a[1] ...a[15] -> a[0] a[4] a[8] a[12] a[1] a[5] a[9] a[13]...a[3] a[7] a[11] a[15]
Run Code Online (Sandbox Code Playgroud)
SSE垂直总和可用于两个通道.但是,只有当数组已经采用特殊格式并且输出可以以特殊格式使用时,这才有效.否则,必须在输入和输出上进行昂贵的重新排列,这将使其比一般情况慢得多.
也许我应该考虑一个不同的前缀和算法(例如二叉树)?
一般情况的代码:
void prefix_sum_omp_sse(double a[], double s[], int n) {
double *suma;
#pragma omp parallel
{
const int ithread = omp_get_thread_num();
const int nthreads = omp_get_num_threads();
#pragma omp single
{
suma = new double[nthreads + 1];
suma[0] = 0;
}
double sum = 0;
#pragma omp for schedule(static) nowait //first parallel pass
for (int i …Run Code Online (Sandbox Code Playgroud) 我希望左移或右移32位的SSE/AVX寄存器,同时移位为零.
让我对我感兴趣的转变更加准确.对于SSE,我想做四个32位浮点数的以下转换:
shift1_SSE: [1, 2, 3, 4] -> [0, 1, 2, 3]
shift2_SSE: [1, 2, 3, 4] -> [0, 0, 1, 2]
Run Code Online (Sandbox Code Playgroud)
对于AVX,我想转移做以下转变:
shift1_AVX: [1, 2, 3, 4, 5, 6, 7, 8] -> [0, 1, 2, 3, 4, 5, 6, 7]
shift2_AVX: [1, 2, 3, 4, 5, 6, 7, 8] -> [0, 0, 1, 2, 3, 4, 5, 6]
shift3_AVX: [1, 2, 3, 4 ,5 ,6, 7, 8] -> [0, 0, 0, 0, 1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
对于SSE,我提出了以下代码
shift1_SSE = …Run Code Online (Sandbox Code Playgroud) 我在OpenMP中实现前缀总和问题,我似乎没有得到任何加速.实际上,并行实现比顺序实现花费的时间更长.
这是我的前缀和的代码:
for (k = 1; k < n; k = kk) {
kk = k << 1;
#pragma omp parallel for
for (i = kk - 1; i < n; i += kk) {
x[i] = x[i-k] + x[i];
}
}
for (k = k >> 1; k > 1; k = kk) {
kk = k >> 1;
#pragma omp parallel for
for (i = k - 1; i < n - kk; i += k) {
x[i …Run Code Online (Sandbox Code Playgroud) 我想矢量化以下操作:
V[i+1] = max(V[i] - c, V[i+1]) for i=1 to n-1 (V[0] = 0)
Run Code Online (Sandbox Code Playgroud)
相应的天真伪代码是:
for (i=0; i < n; i++) {
if (V[i]-c > V[i+1]) V[i+1] = V[i]-c
}
Run Code Online (Sandbox Code Playgroud)
哪些SIMD说明有用?
考虑以下代码,其中a是一个参数数组,float并且s是一个最初未初始化的结果数组float:
s[n - 1] = mu * a[n - 1];
for (int j = n - 2; j >= 0; j--)
s[j] = mu * (a[j] + s[j + 1]);
return s;
Run Code Online (Sandbox Code Playgroud)
有没有机会用SIMD(AVX2)改善这种重复代码的性能?
编辑:我后来发现这个公式/算法被称为"折扣金额",但无法在互联网上找到它的并行版本.
如何找到n数组连续数的最大总和?例如,如果我们的数组是{2,5,3,4,6},n == 2然后输出应该是10(即6 + 4).
我能够为数组大小和小值的小值获得正确的逻辑n.但是当数组大小和n太大,大约10 5时,我的代码需要花费很多时间.请建议一种优化的方法.
我的代码剪断了:
for(int i = 0; i <= n - h; i++) {
int count = 0;
for(int k = i; k < i + h; k++) {
count = count + arr[k];
}
if(i == 0) {
ans[z] = count;
} else if(i != 0) {
if(count < ans[z]) {
ans[z] = count;
}
}
count = 0;
}
Run Code Online (Sandbox Code Playgroud) 编辑 -我的构建系统有问题。我仍在弄清楚到底是什么,但是gcc产生了奇怪的结果(即使它是一个.cpp文件),但是一旦使用,g++它就会按预期工作。
对于我一直遇到的问题,这是一个非常减少的测试用例,其中使用数字包装器类(我认为应该内联)使我的程序慢10倍。
这与优化级别无关(使用-O0和尝试-O3)。
我在包装器类中缺少一些细节吗?
我有以下程序,其中定义了一个包装a double并提供+操作符的类:
#include <cstdio>
#include <cstdlib>
#define INLINE __attribute__((always_inline)) inline
struct alignas(8) WrappedDouble {
double value;
INLINE friend const WrappedDouble operator+(const WrappedDouble& left, const WrappedDouble& right) {
return {left.value + right.value};
};
};
#define doubleType WrappedDouble // either "double" or "WrappedDouble"
int main() {
int N = 100000000;
doubleType* arr = (doubleType*)malloc(sizeof(doubleType)*N);
for (int i = 1; i < N; …Run Code Online (Sandbox Code Playgroud)