【发布时间】:2020-08-04 05:01:08
【问题描述】:
我正在解决一个问题,我想堆叠在不同位置记录的时间序列并提取相干信号。繁重的工作是在 C 中完成的,使用 Python 包装器来提供更友好的界面。我已经达到了对算法的理论正确性感到满意的地步,并希望尽可能地对其进行优化。我对 C 语言的理解足以编写一些可以与 openMP 并行运行的东西,但仅此而已。
问题的优化很重要,因为我正在处理大型数据集 - 最多可堆叠 200 个时间序列,采样率高达 1000Hz,记录数月至数年。使用合理的计算设施,处理可以持续几天到几周。我在连续时间序列的块上运行此堆叠步骤,以免占用内存。
我有几个问题:
有什么明显的我遗漏的东西会有所帮助(通过编译器进行优化,简化算法)?
到目前为止,最显着的收获是优化标志 -Ofast - 我已经阅读并只是想了解更多为什么这更快以及它是否“安全” ' 出于我的目的?
我应该在哪里(除了通过 SO 拖网)了解有关此类问题的更多信息?我的研究中有其他问题想用 C 来解决!
算法
我将每个位置的时间序列连续堆叠在一个 3-D 网格体中。完成给定单元格的完整堆栈后,我需要对结果取幂并按贡献时间序列的数量进行归一化。
#define MAX(a,b) (((a)>(b))?(a):(b))
EXPORT void migrate(double *sigPt, int32_t *indPt, double *mapPt, int32_t fsmp, int32_t lsmp, int32_t nsamp, int32_t nstation, int32_t avail, int64_t ncell, int64_t threads)
{
double *stnPt, *stkPt, *eStkPt;
int32_t *ttpPt;
int32_t ttp;
int32_t to, tm, st;
int64_t cell;
#pragma omp parallel for private(cell,stkPt,eStkPt,ttpPt,st,ttp,tm) num_threads(threads)
for (cell=0; cell<ncell; cell++)
{
stkPt = &mapPt[cell * (int64_t) nsamp];
eStkPt = &mapPt[cell * (int64_t) nsamp];
ttpPt = &indPt[cell * (int64_t) nstation];
for(st=0; st<nstation; st++)
{
ttp = MAX(0,ttpPt[st]);
stnPt = &sigPt[st*(fsmp + lsmp + nsamp) + ttp + fsmp];
for(tm=0; tm<nsamp; tm++)
{
stkPt[tm] += stnPt[tm];
}
}
for(tm=0; tm<nsamp; tm++)
{
eStkPt[tm] = exp(stkPt[tm] / avail);
}
}
}
我目前正在编译:
gcc -shared -fPIC -std=gnu99 ./source.c -fopenmp -Ofast -lm -o ./output
我已阅读:
What GCC optimization flags and techniques are safe across CPUs?
等等。如果我重复一个问题/我的问题定义不明确,请道歉。
【问题讨论】:
-
将这些指针本地化以并行处理并省去私有子句可能会有所帮助。您可能希望确保内部循环经过 simd 优化,并且可能为 exp() 使用 simd 库。
-
好的,我会调查的。我天真地尝试在指数步骤上使用带有#pragma omp simd 的simd 似乎减慢了速度,所以我会去读一些书。谢谢。
标签: c optimization openmp