-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTest_C_OpenACC_2.c
238 lines (185 loc) · 5.95 KB
/
Test_C_OpenACC_2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
**Copyright (C) 2017, Jyong-Jhih Lin.
**All rights reserved.
**Licensed under the GNU Affero General Public License v3.0. See LICENSE file in the project root for full license information.
*/
/*
Test programs for various systems.
Type: C11, OpenACC, standard output, time
compile:
gcc -std=c11 -Wall -Wextra -O0 <file> -lm -static
pgcc -c11 -Minform=inform -O0 -Minfo -ta=host/multicore/tesla,9.0,cc50 <file>
*/
/*
size_t is the unsigned integer type of the result of sizeof , alignof (since C11) and offsetof.
time_t
This is an arithmetic type returned by the functions timer() and mktime() (usually defined as long).
TIME_UTC is int
#define TIME_UTC implementation-defined (since C11)
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <openacc.h>
//size of 2D area
#define COLUMNS 1000
#define ROWS 1000
#define dt_upper_bound 0.01
#define iter_max 4000
int main(void)
{
size_t i=0;
size_t j=0;
double time_difference=0.0;
double time_difference2=0.0;
struct timespec start, end; //C11 only, new method to measure time.
double temp[ROWS+2][COLUMNS+2];
double temp_last[ROWS+2][COLUMNS+2];
double dt;
size_t iter;
timespec_get(&start, 1/*TIME_UTC*/);
//initialize two area variables
dt=100.0;
iter=0;
for(i=0;i<ROWS+2;i++){
for(j=1;j<COLUMNS+1;j++){
temp_last[i][j] = 0.0;
temp[i][j] = 0.0;
}
}
for(i=0;i<ROWS+2;i++){
temp_last[i][0] = 0.0;
temp_last[i][COLUMNS+1] = (100.0/(double)(ROWS+1)) * (double)i;
}
for(j=0;j<COLUMNS+2;j++){
temp_last[0][j] = 0.0;
temp_last[ROWS+1][j] = (100.0/(double)(COLUMNS+1)) * (double)j;
}
//do until dt is smaller than dt_upper_bound or iterations are more than iter_max
while(dt>dt_upper_bound && iter<iter_max){
//average four neighbors
for(i=1;i<=ROWS;i++){
for(j=1;j<=COLUMNS;j++){
temp[i][j] = 0.25 * (temp_last[i-1][j] + temp_last[i+1][j] + temp_last[i][j-1] + temp_last[i][j+1]);
}
}
dt = 0.0;//reset dt
for(i=1;i<=ROWS;i++){
for(j=1;j<=COLUMNS;j++){
dt = fmax( fabs( temp[i][j] - temp_last[i][j] ), dt );
temp_last[i][j] = temp[i][j];
}
}
/*if(iter % 100 == 0){
printf("The iter is %li\n", iter);
printf("The dt is %lf\n", dt);
}*/
iter++;
}
printf("The part 1 is done.\n");
timespec_get(&end, 1/*TIME_UTC*/);
//type "time_t" is defined by the OS, not in C standard.
//Therefore, the size of time_t decides how long the calendar time can be.
time_difference = (double)(end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1.0e9;
/*
*
*
*
*/
//initialize two area variables
dt=100.0;
iter=0;
#pragma acc enter data create(temp[0:ROWS+2][0:COLUMNS+2],temp_last[0:ROWS+2][0:COLUMNS+2])
timespec_get(&start, 1/*TIME_UTC*/);
#pragma acc parallel loop collapse(2) present(temp, temp_last)
for(i=1;i<ROWS+1;i++){
for(j=0;j<COLUMNS+2;j++){
temp_last[i][j] = 0.0;
temp[i][j] = 0.0;
}
}
#pragma acc parallel loop present(temp_last) async
for(i=0;i<ROWS+2;i++){
temp_last[i][0] = 0.0;
}
#pragma acc parallel loop present(temp_last) async
for(i=0;i<ROWS+2;i++){
temp_last[i][COLUMNS+1] = (100.0/(double)(ROWS+1)) * (double)i;
}
#pragma acc parallel loop present(temp_last) async
for(j=0;j<COLUMNS+2;j++){
temp_last[0][j] = 0.0;
}
#pragma acc parallel loop present(temp_last) async
for(j=0;j<COLUMNS+2;j++){
temp_last[ROWS+1][j] = (100.0/(double)(COLUMNS+1)) * (double)j;
}
#pragma acc wait
//do until dt is smaller than 0.01 or iterations are more than 4000
while(dt>dt_upper_bound && iter<iter_max){
//average four neighbors
#pragma acc parallel loop collapse(2) present(temp, temp_last)
for(i=1;i<=ROWS;i++){
for(j=1;j<=COLUMNS;j++){
temp[i][j] = 0.25 * (temp_last[i-1][j] + temp_last[i+1][j] + temp_last[i][j-1] + temp_last[i][j+1]);
}
}
dt = 0.0;//reset dt
#pragma acc enter data copyin(dt)
#pragma acc parallel loop collapse(2) present(temp, temp_last, dt) reduction(max:dt)
for(i=1;i<=ROWS;i++){
for(j=1;j<=COLUMNS;j++){
dt = fmax( fabs( temp[i][j] - temp_last[i][j] ), dt );
temp_last[i][j] = temp[i][j];
}
}
#pragma acc exit data copyout(dt)
/*if(iter % 100 == 0){
printf("The iter is %li\n", iter);
printf("The dt is %lf\n", dt);
}*/
iter++;
}
timespec_get(&end, 1/*TIME_UTC*/);
#pragma acc exit data copyout(temp, temp_last)
printf("The part 2 is done.\n");
time_difference2 = (double)(end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1.0e9;
printf("Type: C11, OpenACC, standard output, time\n");
printf("The time difference is %.9lf\n", time_difference);
printf("The time difference2 is %.9lf\n", time_difference2);
printf("The speed-up ratio is %.9lf\n", time_difference/time_difference2);
printf("The iter is %li\n", iter);
printf("The dt is %lf\n", dt);
return 0;
}
/*
TIMESPEC_GET(3) Library Functions Manual TIMESPEC_GET(3)
NAME
timespec_get - get current calendar time
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <time.h>
#define TIME_UTC 1
int
timespec_get(struct timespec *ts, int base);
DESCRIPTION
The timespec_get function sets the interval pointed to by ts to hold the
current calendar time based on the specified time base in base.
Currently the only supported valid base is TIME_UTC. It returns time
elapsed since epoch.
RETURN VALUES
The timespec_get function returns the passed value of base if successful,
otherwise 0 on failure.
SEE ALSO
clock_gettime(2)
STANDARDS
The timespec_get function conforms to ISO/IEC 9899:2011 ("ISO C11").
HISTORY
This interface first appeared in NetBSD 8.
AUTHORS
Kamil Rytarowski <[email protected]>
NetBSD 8.99 October 4, 2016 NetBSD 8.99
https://www.daemon-systems.org/man/timespec_get.3.html
*/