Skip to content

Commit a20f68f

Browse files
committed
Added Jacobi example using OpenACC with Unified Memory
1 parent 5a680cc commit a20f68f

3 files changed

Lines changed: 212 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#
2+
# Copyright 2015 NVIDIA Corporation
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
CC = pgcc
18+
CCFLAGS = -I./common
19+
ACCFLAGS = -acc -ta=tesla:managed -Minfo=accel
20+
OMPFLAGS = -fast -mp -Minfo
21+
22+
BIN = laplace2d_omp laplace2d_acc
23+
24+
all: $(BIN)
25+
26+
laplace2d_acc: laplace2d.c
27+
$(CC) $(CCFLAGS) $(ACCFLAGS) -o $@ $<
28+
29+
laplace2d_omp: laplace2d.c
30+
$(CC) $(CCFLAGS) $(OMPFLAGS) -o $@ $<
31+
32+
clean:
33+
$(RM) $(BIN)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
2+
*
3+
* Redistribution and use in source and binary forms, with or without
4+
* modification, are permitted provided that the following conditions
5+
* are met:
6+
* * Redistributions of source code must retain the above copyright
7+
* notice, this list of conditions and the following disclaimer.
8+
* * Redistributions in binary form must reproduce the above copyright
9+
* notice, this list of conditions and the following disclaimer in the
10+
* documentation and/or other materials provided with the distribution.
11+
* * Neither the name of NVIDIA CORPORATION nor the names of its
12+
* contributors may be used to endorse or promote products derived
13+
* from this software without specific prior written permission.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
16+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23+
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
28+
#ifndef TIMER_H
29+
#define TIMER_H
30+
31+
#include <stdlib.h>
32+
33+
#ifdef WIN32
34+
#define WIN32_LEAN_AND_MEAN
35+
#include <windows.h>
36+
#else
37+
#include <sys/time.h>
38+
#endif
39+
40+
#ifdef WIN32
41+
double PCFreq = 0.0;
42+
__int64 timerStart = 0;
43+
#else
44+
struct timeval timerStart;
45+
#endif
46+
47+
void StartTimer()
48+
{
49+
#ifdef WIN32
50+
LARGE_INTEGER li;
51+
if(!QueryPerformanceFrequency(&li))
52+
printf("QueryPerformanceFrequency failed!\n");
53+
54+
PCFreq = (double)li.QuadPart/1000.0;
55+
56+
QueryPerformanceCounter(&li);
57+
timerStart = li.QuadPart;
58+
#else
59+
gettimeofday(&timerStart, NULL);
60+
#endif
61+
}
62+
63+
// time elapsed in ms
64+
double GetTimer()
65+
{
66+
#ifdef WIN32
67+
LARGE_INTEGER li;
68+
QueryPerformanceCounter(&li);
69+
return (double)(li.QuadPart-timerStart)/PCFreq;
70+
#else
71+
struct timeval timerStop, timerElapsed;
72+
gettimeofday(&timerStop, NULL);
73+
timersub(&timerStop, &timerStart, &timerElapsed);
74+
return timerElapsed.tv_sec*1000.0+timerElapsed.tv_usec/1000.0;
75+
#endif
76+
}
77+
78+
#endif // TIMER_H
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2015 NVIDIA Corporation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <math.h>
18+
#include <string.h>
19+
#include "timer.h"
20+
21+
int main(int argc, char** argv)
22+
{
23+
int n = 4096;
24+
int m = 4096;
25+
int iter_max = 1000;
26+
27+
const float pi = 2.0f * asinf(1.0f);
28+
const float tol = 1.0e-5f;
29+
float error = 1.0f;
30+
31+
float *restrict A = (float*)malloc(sizeof(float)*n*m);
32+
float *restrict Anew = (float*)malloc(sizeof(float)*n*m);
33+
float *restrict y0 = (float*)malloc(sizeof(float)*n);
34+
35+
memset(A, 0, n * m * sizeof(float));
36+
37+
// set boundary conditions
38+
for (int i = 0; i < m; i++)
39+
{
40+
A[0*m+i] = 0.f;
41+
A[(n-1)*m+i] = 0.f;
42+
}
43+
44+
for (int j = 0; j < n; j++)
45+
{
46+
y0[j] = sinf(pi * j / (n-1));
47+
A[j*m+0] = y0[j];
48+
A[j*m+m-1] = y0[j]*expf(-pi);
49+
}
50+
51+
printf("Jacobi relaxation Calculation: %d x %d mesh\n", n, m);
52+
53+
StartTimer();
54+
int iter = 0;
55+
56+
#pragma omp parallel for shared(Anew)
57+
for (int i = 1; i < m; i++)
58+
{
59+
Anew[0*m+i] = 0.f;
60+
Anew[(n-1)*m+i] = 0.f;
61+
}
62+
#pragma omp parallel for shared(Anew)
63+
for (int j = 1; j < n; j++)
64+
{
65+
Anew[j*m+0] = y0[j];
66+
Anew[j*m+m-1] = y0[j]*expf(-pi);
67+
}
68+
69+
while ( error > tol && iter < iter_max ) {
70+
error = 0.f;
71+
72+
#pragma acc kernels
73+
{
74+
#pragma acc loop independent
75+
for( int j = 1; j < n-1; j++) {
76+
for( int i = 1; i < m-1; i++ ) {
77+
78+
Anew[j*m+i] = 0.25f * ( A[j*m+i+1] + A[j*m+i-1]
79+
+ A[(j-1)*m+i] + A[(j+1)*m+i]);
80+
81+
error = fmaxf( error, fabsf(Anew[j*m+i]-A[j*m+i]));
82+
}
83+
}
84+
85+
#pragma acc loop independent
86+
for( int j = 1; j < n-1; j++) {
87+
for( int i = 1; i < m-1; i++ ) {
88+
A[j*m+i] = Anew[j*m+i];
89+
}
90+
}
91+
}
92+
93+
if(iter % 100 == 0) printf("%5d, %0.6f\n", iter, error);
94+
95+
iter++;
96+
}
97+
98+
double runtime = GetTimer();
99+
100+
printf(" total: %f s\n", runtime / 1000.f);
101+
}

0 commit comments

Comments
 (0)