Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
projects
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
126
projects
Commits
af1e5d47
Commit
af1e5d47
authored
Oct 30, 2020
by
10382
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
📝
2nd Homework Finished!
parent
20da736e
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
109 additions
and
2 deletions
+109
-2
Homework02/README.md
+109
-2
No files found.
Homework02/README.md
View file @
af1e5d47
...
...
@@ -28,4 +28,111 @@
### OpenMP
未完待续......
\ No newline at end of file
#### 未规约实验
尝试采用
`openmp`
实现 0~4 的
`for`
循环加法,首先先尝试未规约的并行循环加法。具体代码如下,
```
c++
int
main
()
{
int
sum
=
0
;
std
::
cout
<<
"Before: "
<<
sum
<<
std
::
endl
;
#pragma omp parallel for
for
(
int
i
=
0
;
i
<
5
;
++
i
)
{
sum
=
sum
+
i
;
std
::
cout
<<
sum
<<
std
::
endl
;
}
std
::
cout
<<
"After: "
<<
sum
<<
std
::
endl
;
return
0
;
}
```
执行后的输出为
```
Before: 0
0
4
3
5
1
After: 5
```
该过程可以理解如下,

首先 4, 3, 1 的线程取到了
`sum`
的值 0,并对其进行了修改,但在将局部变量写回共享变量的时候产生了覆盖(并发一致性中的丢失修改问题),而 2 的线程恰好取到了 3 写回共享内存时的值,因此,最后在其写回共享内存的时候,最终得到的结果为 5。因此,在并行计算的过程中,如果不考虑规约操作,最终得到的可能是错误的结果。
不过有时也可以得到正确的结果,
```
Before: 0
4
4
7
8
10
After: 10
```
有时一个线程甚至会抢着其中一个线程输出
`sum`
和 换行符
`endl`
的过程去输出,导致两个数字在同一行。如下面例子的
`45`
,
```
Before: 0
45
10
7
7
After: 10
```
为了测试该过程中能正确计算出多少次结果,我将该过程循环了 1,000,000 次,计算出了正确计算结果的比例。结果发现,结果具有一定随机性。以下为多次输出的结果
```
0.43192
0.205054
0.472103
0.503719
0.449613
0.632601
0.568709
0.459774
0.487565
0.796675
```
说明线程之间的资源争抢是随机的,不可预测的,所以有必要进行规约操作。
#### 规约实验
在原有的代码基础上加上了对
`sum`
的加法操作规约,
```
c++
int
paraSumRed
()
{
int
sum
=
0
;
std
::
cout
<<
"Before: "
<<
sum
<<
std
::
endl
;
#pragma omp parallel for reduction(+:sum)
for
(
int
i
=
0
;
i
<
5
;
++
i
)
{
sum
=
sum
+
i
;
std
::
cout
<<
sum
<<
std
::
endl
;
}
std
::
cout
<<
"After: "
<<
sum
<<
std
::
endl
;
return
sum
;
}
```
观察输出结果发现,虽然输出存在乱序,但最终结果都正确,同样尝试计算出 1,000,000 次下的概率,得到为 1。
说明并不会出现未规约下的结果错误的情况。
考虑一下前面提到的规约操作的两件事情,为了简化理解,我重新设置了 OpenMP 并行线程数
`OMP_NUM_THREADS`
为 2 (之前为4),并对规约后的过程进行输出,可以发现都是 0,1,3,3,7 的组合,可见规约后的计算过程如下,

确实是规约操作的思想,采用reduction之后,每个线程根据
`reduction(+: sum)`
的声明算出自己的
`sum`
,然后再将每个线程的
`sum`
加起来。
## 总结
规约操作通过将原始任务划分为多个子任务,并将子任务的结果合并以实现多线程下的并行计算,减少计算时间,避免并发一致性的问题。
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment