![](/img/trans.png)
[英]How to declare a global dynamic array with C/OpenACC with PGI compiler
[英]OpenACC bad performance with PGI Compiler
我正在尝试使用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()
,它需要一个float
,建议文字是: 1.0f
与几个计算一样,这个计算: (1.0 - omega)
不会改变,所以这个计算应该在循环之前只进行一次
当我们没有看到串行代码时,我们怎么能说为什么没有编译指示的代码比串行代码慢?
关于:
while (iteracoes_solver < 10001)
变量: iteracoes_solver
被初始化为 0,并且在发布的代码中的任何地方都不会增加。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.