Skip to content

Commit 3de693e

Browse files
committed
Add solution of first task - impelemented loop_mesh_builder
1 parent 87d85fa commit 3de693e

File tree

5 files changed

+102
-47
lines changed

5 files changed

+102
-47
lines changed

PMC-xlogin00.txt

-37
This file was deleted.

PMC-xstupi00.txt

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
Architektury Výpočetních Systémů (AVS 2019)
2+
Projekt č. 2 (PMC)
3+
Login: xstupi00
4+
5+
Úloha 1: Paralelizace původního řešení
6+
===============================================================================
7+
8+
1) Kterou ze smyček (viz zadání) je vhodnější paralelizovat a co způsobuje
9+
neefektivitu paralelizaci té druhé?
10+
11+
1a)
12+
Vhodnejšie je parelelizovať smyčku vo funkcii `LoopMeshBuilder::marchCubes` v
13+
porovnaní s druhou smyčkou vo funkcii `LoopMeshBuilder::evaluateFieldAt`.
14+
15+
1b)
16+
Neefektivita druhej smyčky je spôsobená výrazne väčším overheadom ako je samotný
17+
prínos paralelizácie danej smyčky. Táto smyčka sa nachádza vo funkcii
18+
`LoopMeshBuilder::evaluateFieldAt, ktorá je volaná 8x pre každý beh funkcie
19+
`BaseMeshBuilder::buildCube`, pre každý vrchol kocky raz. Pre každú kocku, tak
20+
dochádza k vytvoreniu a následnému zrušeniu daného počtu vlákien (napr. 16) až 8x,
21+
čo práve spôsobuje veľký overhead a tým zhoršenie celkovej výkonnosti programu.
22+
23+
-------------------------------------------------------------------------------
24+
25+
2) Jaké plánování (rozdělení práce mezi vlákna) jste zvolili a proč?
26+
Jaký vliv má velikost "chunk" při dynamickém plánování (8, 16, 32, 64)?
27+
28+
29+
2a)
30+
Zvolil som dynamický typ plánovania s hodnotou chunk-size=16 (schedule(dynamic, 16)).
31+
Tento typ plánovania dosahoval pri testovaní rôznych variant o niečo lepšie výsledky
32+
ako statické plánovanie a v porovnaní s typom `guided` dosahoval takmer rovnaké
33+
výsledky. Výpočet pre každú kocku trvá približne rovnaký čas, takže môžme povedať, že
34+
práca je vhodne distribuovaná medzi jednotlivé vlákna už v základe. Malý rozdiel medzi
35+
statickým a dynamickým plánovaním môže byť spôsobený tým, že v prípadoch, kedy nie sú
36+
všetky vrcholy kocky pod alebo nad povrchom (povrch pretína kocku) prebieha oproti
37+
zvyšným iteráciam aj interpolácia vybraných polygónov, čo spôsobí o niečo dlhšie
38+
trvanie výpočtu v danej iterácií. Takýchto iterácií, v ktorých dochádza k
39+
interpolácií polygónov, je však z celkového počtu minimum (cca < 8% u bun_zipper_res a
40+
< 5% u dragon_vrip_res) a preto dynamické plánovanie nespôsobuje väčši rozdiel v tomto
41+
procese paralelizácie.
42+
43+
44+
2b)
45+
Pri voľbe dynamického plánovania s rôznou hodnotou parametru `chunk-size` som
46+
nezaznamenal žiadne výrazné zmeny vo výkonnosti programu.
47+
48+
-------------------------------------------------------------------------------
49+
50+
3) Jakým způsobem zajišťujete ukládání trojúhelníků z několika vláken současně?
51+
52+
Použitím pragmy `omp critical` vo funkcii `LoopMeshBuilder::emitTriangle` pred
53+
uložením daného trojuholníka `BaseMeshBuilder::Triangle_t` do vektora už
54+
uložených trojuholníkov `LoopMeshBuilder::mTriangles`. Táto pragma identifikuje
55+
sekcie kódu, ktoré musia byť vykonávané len jedným vláknom v danom čase a
56+
zabezpečuje tak, že zápis do vektora bude realizovať vždy len jedno vlákno.
57+
V prípade, že niektoré z vlákien práve realizuje zápis do vektora a súčasne
58+
iné vlákno má taktiež požiadavku na zápis, bude musieť toto vlákno čakať na
59+
začiatku kritickej sekcie dokiaľ prvé vlákno nedokončí operáciu zápisu a tým
60+
vypadne z kritickej sekcie, čím umožní vstup inému vláknu, ktoré čaká na vstupe.
61+
62+
63+
Úloha 2: Paralelní průchod stromem
64+
===============================================================================
65+
66+
1) Stručně popište použití OpenMP tasků ve vašem řešení.
67+
68+
2) Jakým způsobem jste realizovali sesbírání celkového počtu trojúhelníků?
69+
70+
3) Jaký vliv má na vaše řešení tzv. "cut-off"? Je vhodné vytvářet nový
71+
task pro každou krychli na nejnižší úrovni?
72+
73+
4) Jakým způsobem zajišťujete ukládání trojúhelníků z několika vláken současně?
74+
75+
Úloha 2: Grafy škálování obou řešení
76+
===============================================================================
77+
78+
1) Stručně zhodnoťte efektivitu vytvořených řešení (na základě grafů škálování).
79+
80+
2) V jakém případě (v závislosti na počtu bodů ve vstupním souboru a velikosti
81+
mřížky) bude vaše řešení 1. úlohy neefektivní? (pokud takový případ existuje)
82+
83+
3) Je (nebo není) stromový algoritmus efektivnější z pohledu slabého škálování
84+
vzhledem ke vstupu?

commands.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ qsub -A DD-19-32 -q qexp -l select=1:ncpus=16,walltime=1:00:00 -I
22
ml intel CMake Python/3.6.1
33
cmake . -DCMAKE_BUILD_TYPE=Release
44
make -j
5-
./PMC ../data/bun_zipper_res4.pts bun_zipper_res4.obj --builder=loop
5+
./PMC ../data/bun_zipper_res1.pts bun_zipper_res1.obj --builder=loop

notes.txt

+8
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ GRID
1717
-> dĺžka hrany diskretizačnej mriežky a s ňou rozlíšenie diskretizácie a celkový počet "MarchingCubes" (N = g^3)
1818
-> BaseMeshBuilder.mGridSize;
1919

20+
----------------------------------------------------------------------------------------------
21+
| static | 13732 | 13768 | 13743 | 13742 | 13759 | 13758 | 13741 | 13775 | 13743 | 13753 |
22+
| dynamic 8 | 13698 | 13707 | 13708 | 13721 | 13725 | 13703 | 13718 | 13711 | 13704 | 13701 |
23+
| dynamic 16 | 13709 | 13730 | 13712 | 13712 | 13722 | 13722 | 13722 | 13731 | 13714 | 13710 |
24+
| dynamic 32 | 13707 | 13716 | 13734 | 13716 | 13741 | 13725 | 13723 | 13739 | 13721 | 13719 |
25+
| dynamic 64 | 13746 | 13726 | 13727 | 13743 | 13744 | 13734 | 13744 | 13738 | 13745 | 13736 |
26+
| guided | 13710 | 13742 | 13728 | 13704 | 13711 | 13710 | 13697 | 13710 | 13713 | 13705 |
27+
----------------------------------------------------------------------------------------------

src/parallel_builder/loop_mesh_builder.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ LoopMeshBuilder::LoopMeshBuilder(unsigned gridEdgeSize)
1919

2020
}
2121

22-
unsigned LoopMeshBuilder::marchCubes(const ParametricScalarField &field)
23-
{
22+
unsigned LoopMeshBuilder::marchCubes(const ParametricScalarField &field) {
2423
// 1. Compute total number of cubes in the grid
2524
// N = g^3 = mGridSize^3
2625
size_t totalCubesCount = mGridSize * mGridSize * mGridSize;
2726

2827
unsigned totalTriangles = 0;
2928

3029
// 2. Loop over each coordinate in the 3D grid.
30+
#pragma omp parallel for default(shared) reduction(+:totalTriangles) schedule(dynamic, 32)
3131
for (size_t i = 0; i < totalCubesCount; ++i) {
3232
// 3. Compute 3D position in the grid.
3333
Vec3_t<float> cubeOffset(i % mGridSize,
@@ -43,8 +43,7 @@ unsigned LoopMeshBuilder::marchCubes(const ParametricScalarField &field)
4343
return totalTriangles;
4444
}
4545

46-
float LoopMeshBuilder::evaluateFieldAt(const Vec3_t<float> &pos, const ParametricScalarField &field)
47-
{
46+
float LoopMeshBuilder::evaluateFieldAt(const Vec3_t<float> &pos, const ParametricScalarField &field) {
4847
// NOTE: This method is called from "buildCube(...)"!
4948

5049
// 1. Store pointer to and number of 3D points in the field
@@ -56,11 +55,11 @@ float LoopMeshBuilder::evaluateFieldAt(const Vec3_t<float> &pos, const Parametri
5655

5756
// 2. Find minimum square distance from points "pos" to any point in the
5857
// field.
59-
for(unsigned i = 0; i < count; ++i)
60-
{
61-
float distanceSquared = (pos.x - pPoints[i].x) * (pos.x - pPoints[i].x);
62-
distanceSquared += (pos.y - pPoints[i].y) * (pos.y - pPoints[i].y);
63-
distanceSquared += (pos.z - pPoints[i].z) * (pos.z - pPoints[i].z);
58+
//#pragma omp parallel for default(shared) reduction(min:value) schedule(static)
59+
for (unsigned i = 0; i < count; ++i) {
60+
float distanceSquared = (pos.x - pPoints[i].x) * (pos.x - pPoints[i].x);
61+
distanceSquared += (pos.y - pPoints[i].y) * (pos.y - pPoints[i].y);
62+
distanceSquared += (pos.z - pPoints[i].z) * (pos.z - pPoints[i].z);
6463

6564
// Comparing squares instead of real distance to avoid unnecessary
6665
// "sqrt"s in the loop.
@@ -77,5 +76,6 @@ void LoopMeshBuilder::emitTriangle(const BaseMeshBuilder::Triangle_t &triangle)
7776
// Store generated triangle into vector (array) of generated triangles.
7877
// The pointer to data in this array is return by "getTrianglesArray(...)" call
7978
// after "marchCubes(...)" call ends.
79+
#pragma omp critical(emitTriangle)
8080
mTriangles.push_back(triangle);
8181
}

0 commit comments

Comments
 (0)