- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
刚开始接触OPENMP,想用它来求解波动方程,串口代码在这里:
#include <time.h>
#include <stdio.h>
#include <omp.h>
#include <math.h>
#define GRID_SZ 3000
#define ARR_SZ GRID_SZ * GRID_SZ
#define PEAK_SZ 31
double *process_withoutomp() {
double start = omp_get_wtime();
int i, j;
double dt = 0.04, C = 16, K = 0.1, h = 6;
double *data, *olddata, *newdata, *tmp;
double x[PEAK_SZ][PEAK_SZ], linspace[PEAK_SZ], delta = 2.0/(PEAK_SZ-1.0);
data = (double*)malloc(sizeof(double)*ARR_SZ);
olddata = (double*)malloc(sizeof(double)*ARR_SZ);
newdata = (double*)malloc(sizeof(double)*ARR_SZ);
for(i = 0; i < ARR_SZ; i++){
data[i] = 1.0;
}
for(i = 0; i < PEAK_SZ; i++){
linspace[i] = -1.0 + delta * i;
}
for(i = 0; i < PEAK_SZ; i++){
for(j = 0; j < PEAK_SZ; j++){
x[i][j] = linspace[i];
}
}
for(i = 0; i < PEAK_SZ; i++){
for(j = 0; j < PEAK_SZ; j++){
data[(i+20)*GRID_SZ+j+20] += h * exp( -5 * (pow(x[i][j], 2 ) + pow(x[j][i], 2 )));
}
}
for(i = 0; i < ARR_SZ; i++){
olddata[i] = data[i];
}
for(i = 0; i < 20; i++){
sequential_update_withoutomp( data, olddata, newdata, C, K, dt);
tmp = olddata;
olddata = data;
data = newdata;
newdata = tmp;
}
double end = omp_get_wtime();
printf("without omp spend: %f\n",end-start);
return data;}void sequential_update_withoutomp(double *data, double *olddata, double *newdata, double C, double K, double dt ){
int i, j, add_i, sub_i, add_j, sub_j;
double pot;
for( i = 0; i < GRID_SZ; i++){
for( j = 0; j < GRID_SZ; j++){
add_i = i+1 >= GRID_SZ ? i : i+1;
add_j = j+1 >= GRID_SZ ? j : j+1;
sub_i = i-1 < 0 ? 0 : i-1;
sub_j = j-1 < 0 ? 0 : j-1;
pot = data[add_i*GRID_SZ+j]+
data[sub_i*GRID_SZ+j]+
data[add_j+i*GRID_SZ]+
data[sub_j+i*GRID_SZ]-
4*data[i*GRID_SZ+j];
newdata[i * GRID_SZ + j] =
( pow(C * dt, 2) * pot * 2 + 4 * data[i * GRID_SZ + j] - olddata[i * GRID_SZ + j] *(2 - K * dt) ) / (2 + K * dt);
}
}}
这里是使用的版本:
double *process_withomp() {
double start = omp_get_wtime();
int i, j;
double dt = 0.04, C = 16, K = 0.1, h = 6;
double *data, *olddata, *newdata, *tmp;
double x[PEAK_SZ][PEAK_SZ], linspace[PEAK_SZ], delta = 2.0/(PEAK_SZ-1.0);
data = (double*)malloc(sizeof(double)*ARR_SZ);
olddata = (double*)malloc(sizeof(double)*ARR_SZ);
newdata = (double*)malloc(sizeof(double)*ARR_SZ);
#pragma omp parallel for private(i) schedule(auto)
for(i = 0; i < ARR_SZ; i++){
data[i] = 1.0;
}
#pragma omp parallel for private(i,j) schedule(auto)
for(i = 0; i < PEAK_SZ; i++){
linspace[i] = -1.0 + delta * i;
for(j = 0; j < PEAK_SZ; j++) {
x[i][j] = linspace[i];
}
}
#pragma omp barrier
#pragma omp parallel for private(i,j) schedule(auto)
for(i = 0; i < PEAK_SZ; i++){
for(j = 0; j < PEAK_SZ; j++){
data[(i+20)*GRID_SZ+j+20] += h * exp( -5 * (pow(x[i][j], 2 ) + pow(x[j][i], 2 )));
}
}
#pragma omp barrier
#pragma omp parallel for private(i) schedule(auto)
for(i = 0; i < ARR_SZ; i++){
olddata[i] = data[i];
}
#pragma omp barrier
for(i = 0; i < 20; i++) {
sequential_update_withomp( data, olddata, newdata, C, K, dt);
tmp = olddata;
olddata = data;
data = newdata;
newdata = tmp;
}
double end = omp_get_wtime();
printf("with omp spend: %f\n",end-start);
return data;}void sequential_update_withomp(double *data, double *olddata, double *newdata, double C, double K, double dt ) {
int i, j;
double pot;
#pragma omp parallel for private(i,j,pot) schedule(auto)
for( i = 0; i < GRID_SZ; i++) {
for( j = 0; j < GRID_SZ; j++) {
pot = data[(i+1 >= GRID_SZ ? i : i+1)*GRID_SZ+j]+
data[(i-1 < 0 ? 0 : i-1)*GRID_SZ+j]+
data[(j+1 >= GRID_SZ ? j : j+1)+i*GRID_SZ]+
data[(j-1 < 0 ? 0 : j-1)+i*GRID_SZ]
-4*data[i*GRID_SZ+j];
newdata[i * GRID_SZ + j] =
(pow(C * dt, 2) * pot * 2 + 4 * data[i * GRID_SZ + j] - olddata[i * GRID_SZ + j]
* (2 - K * dt))
/ (2 + K * dt);
}
}}
这个版本运行良好,但是当我尝试使用任务替换它时,结果是正确的,但花费的时间更多:
double *process_withomp1() {
double start = omp_get_wtime();
int i, j;
double dt = 0.04, C = 16, K = 0.1, h = 6;
double *data, *olddata, *newdata, *tmp;
double x[PEAK_SZ][PEAK_SZ], linspace[PEAK_SZ], delta = 2.0/(PEAK_SZ-1.0);
data = (double*)malloc(sizeof(double)*ARR_SZ);
olddata = (double*)malloc(sizeof(double)*ARR_SZ);
newdata = (double*)malloc(sizeof(double)*ARR_SZ);
#pragma omp parallel for private(i) schedule(auto)
for(i = 0; i < ARR_SZ; i++){
data[i] = 1.0;
}
#pragma omp parallel for private(i,j) schedule(auto)
for(i = 0; i < PEAK_SZ; i++){
linspace[i] = -1.0 + delta * i;
for(j = 0; j < PEAK_SZ; j++) {
x[i][j] = linspace[i];
}
}
#pragma omp barrier
#pragma omp parallel for private(i,j) schedule(auto)
for(i = 0; i < PEAK_SZ; i++){
for(j = 0; j < PEAK_SZ; j++){
data[(i+20)*GRID_SZ+j+20] += h * exp( -5 * (pow(x[i][j], 2 ) + pow(x[j][i], 2 )));
}
}
#pragma omp barrier
#pragma omp parallel for private(i) schedule(auto)
for(i = 0; i < ARR_SZ; i++){
olddata[i] = data[i];
}
#pragma omp barrier
for(i = 0; i < 20; i++) {
sequential_update_withomp1( data, olddata, newdata, C, K, dt);
tmp = olddata;
olddata = data;
data = newdata;
newdata = tmp;
}
double end = omp_get_wtime();
printf("with omp spend: %f\n",end-start);
return data;}
void sequential_update_withomp1(double *data, double *olddata, double *newdata, double C, double K, double dt ) {
int i, j;
double pot;
#pragma omp parallel private(i,j,pot)
for( i = 0; i < GRID_SZ; i++) {
for( j = 0; j < GRID_SZ; j++) {
#pragma omp task
{
pot = data[(i+1 >= GRID_SZ ? i : i+1)*GRID_SZ+j]+
data[(i-1 < 0 ? 0 : i-1)*GRID_SZ+j]+
data[(j+1 >= GRID_SZ ? j : j+1)+i*GRID_SZ]+
data[(j-1 < 0 ? 0 : j-1)+i*GRID_SZ]
-4*data[i*GRID_SZ+j];
newdata[i * GRID_SZ + j] =
(pow(C * dt, 2) * pot * 2 + 4 * data[i * GRID_SZ + j] - olddata[i * GRID_SZ + j]
* (2 - K * dt))
/ (2 + K * dt);
}
}
}}
在我的 mac 上,serial 版本大约需要 7.7s,for 版本需要 3.7s,但是任务使用 53s。
有人知道这里出了什么问题吗?
提前致谢
最佳答案
这里有两点需要考虑:
在您的代码中,a) 太小,b) 已损坏。
一)在您的 task
示例中,内部循环的一次迭代 是一项任务,而在 parallel for
示例中,n 次迭代外循环是并行化的,即每个线程处理外循环的大量迭代。使用 schedule(static, 1)
,一个外部迭代将是每个线程的工作大小。请记住,所有并行都会增加开销,用于同步内容、簿记等。增加的成本必须通过并行执行的执行速度提高来补偿。找到合适的工作量是至关重要的,您希望尽可能多地保持一切忙碌,也许更多的工作量可以给调度程序一些空间来补偿任务/ block 之间的负载不平衡,但要尽可能少以保持较小的开销。
b)在您的并行区域中运行循环,意味着每个线程都在运行整个循环嵌套并多次创建所有任务。这就像并行运行串行程序多次。
void sequential_update_withomp1(double *data, double *olddata, double *newdata, double C, double K, double dt ) {
// ....
#pragma omp parallel private(i,j,pot)
{
// split loop among threads of parallel region
// i.e. create tasks in parallel
#pragma omp for
for( i = 0; i < GRID_SZ; i++) {
// coarse grained tasks (as in parallel for version)
#pragma omp task
{
// each inner for loop is one task
for( j = 0; j < GRID_SZ; j++) {
// ...
}
} // task
} // parallel for
} // parallel region
这给了我(2 个核心 x 2 个超线程):
serial: 4.839213
parallel for: 2.529813
task: 2.817615
注意:在这里实际使用任务没有意义,因为它们只会在并行 for 循环之上增加开销。
关于c - 为什么 OMP 任务运行速度比 OMP 慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48129831/
自己试试看: import pandas as pd s=pd.Series(xrange(5000000)) %timeit s.loc[[0]] # You need pandas 0.15.1
我最近开始使用 Delphi 中的 DataSnap 来生成 RESTful Web 服务。在遵循 Marco Cantu 本人和互联网上其他几个人的指导后,我成功地使整个“链条”正常工作。 但是有一
我一直在为操作系统类(class)编写以下代码,但结果有些奇怪。该代码创建x线程并同时运行它们,以便将两个平方矩阵相乘。每个线程将输入矩阵的Number_of_rows/Number_of_threa
我正在尝试确定何时使用 parallel包以加快运行某些分析所需的时间。我需要做的一件事是创建矩阵,比较具有不同行数的两个数据框中的变量。我在 StackOverflow 上问了一个关于有效方法的问题
我最近对我的代码进行了一些清理,并在此过程中更改了此内容(不完全是真实的代码): read = act readSTRef test1 term i var = do t v^!terms.
我正在计时查询和同一个查询的执行时间,分页。 foreach (var x in productSource.OrderBy(p => p.AdminDisplayName) .Wher
我正在开发一个项目 (WPF),我有一个 Datagrid 从数据库加载超过 5000 条记录,所以我使用 BackgroundWorker 来通知用户数据正在加载,但它太慢了,我需要等待将近 2分钟
我在查询中添加 ORDER BY 时遇到问题。没有 ORDER BY 查询大约需要 26ms,一旦我添加 ORDER BY,它大约需要 20s。 我尝试了几种不同的方法,但似乎可以减少时间。 尝试 F
我是 Android 开发新手,遇到了性能问题。当我的 GridView 有太多项目时,它会变得有点慢。有什么方法可以让它运行得更快一些吗? 这是我使用的代码: 适配器: public class C
这里的要点是: 1.设置query_cache_type = 0;重置查询缓存; 2.在 heidisql(或任何其他客户端 UI)中运行任何查询 --> 执行,例如 45 毫秒 3.使用以下代码运行
想象下表: CREATE TABLE drops( id BIGSERIAL PRIMARY KEY, loc VARCHAR(5) NOT NULL, tag INT NOT
我的表 test_table 中的示例数据: date symbol value created_time 2010-01-09 symbol1
首先,如果已经有人问过这个问题,我深表歉意,至少我找不到任何东西。 无论如何,我将每 5 分钟运行一次 cron 任务。该脚本加载 79 个外部页面,而每个页面包含大约 200 个我需要在数据库中检查
我有下面的 SQL 代码,它来自 MySQL 数据库。现在它给了我期望的结果,但是查询很慢,我想我应该在进一步之前加快这个查询的速度。 表agentstatusinformation有: PKEY(主
我需要获取一个对象在 Core Data 中数千个其他对象之间的排名。现在,这是我的代码: - (void)rankMethod { //Fetch all objects NSFet
我正在编写一个应用程序,我需要在其中读取用户的地址簿并显示他所有联系人的列表。我正在测试的 iPhone 有大约 100 个联系人,加载联系人确实需要很多时间。 ABAddressBookRef ad
我正在使用 javascript 将 160 行添加到包含 10 列的表格中。如果我这样做: var cellText = document.createTextNode(value); cell.a
我是 Swift 的新手,我已经设置了一个 tableView,它从 JSON 提要中提取数据并将其加载到表中。 表格加载正常,但是当表格中有超过 10 个单元格时,它会变得缓慢且有些滞后,特别是它到
我在 InitializeCulture 和 Page_PreInit 事件之间的 asp.net 页面中遇到性能问题。当我重写 DeterminePostBackMode() 时,我发现问题出在 b
我在 Hetzner 上有一个带有 256GB RAM 6 个 CPU(12 个线程) 的专用服务器,它位于德国。我有 CENTOS 7.5。 EA4。 我的问题是 SSL。每天大约 2 小时,我们在
我是一名优秀的程序员,十分优秀!