c - PGI 编译器的 OpenACC 性能不佳
问题描述
我正在尝试使用OpenACC制作我的期末论文,以提高代码的性能。但是,优化的代码比我尝试了很多东西的串行代码差,但没有一个有效。如果有人可以帮助我,我将不胜感激。
1332 void SOR()
1333 {
1334 iteracoes_solver = 0;
1335
1336
1337 {
1338
1339 #pragma acc data copy(AC_lin[2:nx*ny], Po1_lin[2:nx*ny], AUXW1[2:nx*ny], Qo_lin[2:nx*ny], Tgx[2:nx*ny], Po3_lin[2:nx*ny], Tgy[2:nx*ny], P_auxi[2:nx*ny], vetErro[2:nx*ny]) \
1340 copyin(AC_lin[2:nx*ny], Tgx[2:nx*ny], Tgy[2:nx*ny])
1341 while (iteracoes_solver < 10001)
1342 {
1343
1344
1345 //#pragma acc kernels loop private(n) copyin(P_auxi[0:nxy]) vector(512)
1346 for (n = 1; n <= nxy; n++)
1347 P_auxi[n] = Po3_lin[n];
1348
1349
1350 {
1351
1352 erro = 0.0;
1353
1354 if (total_iter == 10000)
1355 {
1356 printf("---> TEMPO=%g\n---> Numero maximo de iteracoes atingido no solver\n---> Corrigir parametros\n", tempo_atual);//getch();
1357 exit_tool();
1358 }
1359
1360 n = 1;
1361 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n] * Po3_lin[n + 1]) + (Tgy[n] * Po3_lin[n + nx]) + ((1 - AUXW1[n]));
1362 Paux = auxf1 / (AC_lin[n] + Tgx[n] + Tgy[n] + (1 - AUXW1[n]));
1363 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1364 vetErro[n] = fabs(Po3_lin[n] - Paux);
1365 Po3_lin[n] = Paux;
1366
1367 n = nx;
1368 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n - 1] * Po3_lin[n - 1]) + (Tgy[n] * Po3_lin[n + nx]) + ((1 - AUXW1[n]));
1369 Paux = auxf1 / (AC_lin[n] + Tgx[n - 1] + Tgy[n] + ((1 - AUXW1[n])));
1370 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1371 vetErro[n] = fabs(Po3_lin[n] - Paux);
1372 Po3_lin[n] = Paux;
1373
1374 auxi11 = nxy - nx;
1375
1376 n = auxi11 + 1;
1377 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n] * Po3_lin[n + 1]) + (Tgy[n - nx] * Po3_lin[n - nx]) + ((1 - AUXW1[n]));
1378 Paux = auxf1 / (AC_lin[n] + Tgx[n] + Tgy[n - nx] + ((1 - AUXW1[n])));
1379 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1380 vetErro[n] = fabs(Po3_lin[n] - Paux);
1381 Po3_lin[n] = Paux;
1382
1383 n = nxy;
1384 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n - 1] * Po3_lin[n - 1]) + (Tgy[n - nx] * Po3_lin[n - nx]) + ((1 - AUXW1[n]));
1385 Paux = auxf1 / (AC_lin[n] + Tgx[n - 1] + Tgy[n - nx] + ((1 - AUXW1[n])));
1386 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1387 vetErro[n] = fabs(Po3_lin[n] - Paux);
1388 Po3_lin[n] = Paux;
1389
1390
1391
1392 #pragma acc parallel loop private(n)
1393 for (n = 2; n < nx; n++)
1394 {
1395 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n] * Po3_lin[n + 1]) + (Tgx[n - 1] * Po3_lin[n - 1]) + (Tgy[n] * Po3_lin[n + nx]) + ((1 - AUXW1[n]));
1396 Paux = auxf1 / (AC_lin[n] + Tgx[n] + Tgx[n - 1] + Tgy[n] + ((1 - AUXW1[n])));
1397 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1398 vetErro[n] = fabs(Po3_lin[n] - Paux);
1399 Po3_lin[n] = Paux;
1400 }
1401
1402
1403
1404 #pragma acc parallel loop private(n)
1405 for (j = 2; j < ny; j++)
1406 {
1407 auxi11 = nx * (j - 1);
1408
1409 n = auxi11 + 1;
1410 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n] * Po3_lin[n + 1]) + (Tgy[n] * Po3_lin[n + nx]) + (Tgy[n - nx] * Po3_lin[n - nx]) + ((1 - AUXW1[n]));
1411 Paux = auxf1 / (AC_lin[n] + Tgx[n] + Tgy[n] + Tgy[n - nx] + ((1 - AUXW1[n])));
1412 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1413 vetErro[n] = fabs(Po3_lin[n] - Paux);
1414 Po3_lin[n] = Paux;
1415 }
1416
1417
1418
1419 //#pragma acc kernels
1420 for (j = 2; j < ny; j++)
1421 {
1422 auxi11 = nx * (j - 1);
1423
1424 n = auxi11 + nx;
1425 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n - 1] * Po3_lin[n - 1]) + (Tgy[n] * Po3_lin[n + nx]) + (Tgy[n - nx] * Po3_lin[n - nx]) + ((1 - AUXW1[n]));
1426 Paux = auxf1 / (AC_lin[n] + Tgx[n - 1] + Tgy[n] + Tgy[n - nx] + ((1 - AUXW1[n])));
1427 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1428 vetErro[n] = fabs(Po3_lin[n] - Paux);
1429 Po3_lin[n] = Paux;
1430
1431 }
1432
1433
1434 auxi11 = nxy - nx;
1435
1436
1437
1438 //#pragma acc kernels
1439 for (i = 2; i < nx; i++)
1440 {
1441 n = auxi11 + i;
1442 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n] * Po3_lin[n + 1]) + (Tgx[n - 1] * Po3_lin[n - 1]) + (Tgy[n - nx] * Po3_lin[n - nx]) + ((1 - AUXW1[n]));
1443 Paux = auxf1 / (AC_lin[n] + Tgx[n] + Tgx[n - 1] + Tgy[n - nx] + ((1 - AUXW1[n])));
1444 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1445 vetErro[n] = fabs(Po3_lin[n] - Paux);
1446 Po3_lin[n] = Paux;
1447 }
1448 }
1449
1450
1451
1452
1453 //#pragma acc kernels loop private(auxf1,Paux,i,j,n) vector(512) independent
1454 for (j = 2; j < ny; j++)
1455 {
1456 for (i = 2 + (j % 2); i < nx; i += 2)
1457 {
1458 n = (nx * (j - 1)) + i;
1459 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n] * Po3_lin[n + 1]) + (Tgx[n - 1] * Po3_lin[n - 1]) + (Tgy[n] * Po3_lin[n + nx]) + (Tgy[n - nx] * Po3_lin[n - nx]) + ((1 - AUXW1[n]));
1460 Paux = auxf1 / (AC_lin[n] + Tgx[n] + Tgx[n - 1] + Tgy[n] + Tgy[n - nx] + ((1 - AUXW1[n])));
1461 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1462 vetErro[n] = fabs(Po3_lin[n] - Paux);
1463 Po3_lin[n] = Paux;
1464 }
1465 }
1466
1467
1468 //#pragma acc kernels loop private(auxf1,Paux,i,j,n) vector(512) independent
1469 for (j = 2; j < ny; j++)
1470 {
1471 for (i = 3 - (j % 2); i < nx; i += 2)
1472 {
1473 n = (nx * (j - 1)) + i;
1474 auxf1 = (AC_lin[n] * Po1_lin[n]) + (AUXW1[n] * Qo_lin[n]) + (Tgx[n] * Po3_lin[n + 1]) + (Tgx[n - 1] * Po3_lin[n - 1]) + (Tgy[n] * Po3_lin[n + nx]) + (Tgy[n - nx] * Po3_lin[n - nx]) + ((1 - AUXW1[n]));
1475 Paux = auxf1 / (AC_lin[n] + Tgx[n] + Tgx[n - 1] + Tgy[n] + Tgy[n - nx] + ((1 - AUXW1[n])));
1476 Paux = (omega * Paux) + ((1.0 - omega) * P_auxi[n]);
1477 vetErro[n] = fabs(Po3_lin[n] - Paux);
1478 Po3_lin[n] = Paux;
1479 }
1480 }
1481
1482
1483 #pragma acc parallel loop private(n)
1484 for (n = 0; n < nxy; n++) {
1485 erro += vetErro[n];
1486 }
1487
1488
1489 if ((erro / nxy < tol)) {
1490 //#pragma omp cancel parallel
1491 break;
1492 }
1493 iteracoes_solver += 1;
1494 }
1495
1496 }
1497 }
我不能放所有的de代码,所以我放了一部分代码。我评论了一些编译指示以供测试。当我的 nx=ny >=1000 时,串行代码优于优化代码。我不明白的另一件事是我删除了代码的所有 pragma,然后运行 PGI 编译器来优化代码,串行代码更好,我不知道为什么。最后,我有两个问题:
1 - 我做错了什么?2 - 为什么没有编译指示的代码比串行代码差?
最好的问候,布雷诺。
更新:我忘了把编译信息。我运行代码
pgcc -ta=multicore -Minfo=all file.c -o file.exe
并生成
1360, FMA (fused multiply-add) instruction(s) generated
1392, Generating Multicore code
1393, #pragma acc loop gang
1393, FMA (fused multiply-add) instruction(s) generated
1404, Generating Multicore code
1405, #pragma acc loop gang
1405, FMA (fused multiply-add) instruction(s) generated
1420, FMA (fused multiply-add) instruction(s) generated
1439, FMA (fused multiply-add) instruction(s) generated
1456, FMA (fused multiply-add) instruction(s) generated
1471, FMA (fused multiply-add) instruction(s) generated
1483, Generating Multicore code
1484, #pragma acc loop gang
1485, Generating implicit reduction(+:erro)
解决方案
通常,使用 OMP 功能会导致大量上下文切换,这实际上会减慢代码的执行速度。SO OMP 非常适合 I/O 绑定代码,但不适用于 CPU 绑定代码。
重复计算应移到循环之前:
什么是:2:nx*ny
?
索引变量的“范围”应尽可能合理。因此,在编写for()
语句时,第一个参数也应该声明索引变量,对于大多数这些for()
语句来说,它类似于:
for( size_t i = 0; .,.. )
关于:1.0
这是一个double
文字,但是代码正在调用fabs()
,它需要 a float
,建议文字是:1.0f
与几个计算一样,这个计算:(1.0 - omega)
不会改变,所以这个计算应该只做一次,在循环之前
当我们没有看到串行代码时,我们怎么能说为什么没有编译指示的代码比串行代码慢?
关于:
while (iteracoes_solver < 10001)
变量:iteracoes_solver
被初始化为 0,并且在发布的代码中的任何地方都没有递增。
推荐阅读
- java - 通过没有 Maven 的可执行 JAR 从 cmdline 执行 Cucumber 测试
- redis - 如何将 RDB 加载到 redis 集群
- python - LSTMCELL 的替代品,因为 tensorflow_core.compat.v1' 没有属性 'contrib'
- python - 在终端中找不到用于 python 执行的 pip3 安装库
- asp.net-mvc - 尝试发布到控制器时收到 404 错误
- java - 子类可以在java中留下未实现的抽象方法吗?
- android - android片段中的IllegalStateException错误
- angular - Angular2+、SpringBoot 2.1.9、Keycloak:CORS 配置不起作用
- python - 如何将打印语句与返回语句放在同一行?
- javascript - 从视图到控制器获取选中的复选框列表数据