metalsvm/apps/laplace.c

310 lines
6.7 KiB
C

/*
* Copyright 2010 Carsten Clauss, Pablo Reble, Stefan Lankes
* Chair for Operating Systems, RWTH Aachen University
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of MetalSVM.
*/
#include <metalsvm/stdlib.h>
#include <metalsvm/stdio.h>
#include <asm/irqflags.h>
#include <asm/svm.h>
#include "tests.h"
#ifdef START_KERNEL_LAPLACE
#include <asm/RCCE.h>
#include <asm/iRCCE.h>
#define _LAPLACE_SHMEM_
//#define _USE_GFX
#ifdef _LAPLACE_SHMEM_
#define SINGLE_CONNECT 1
#else
#define SINGLE_CONNECT 0
#endif
#ifdef _USE_GFX
#include "gfx_generic.h"
#include "gfx_client.h"
#endif
#define ABS(a) (((a) < 0) ? -(a) : (a))
#define MAX(a,b) (((a) < (b)) ? (b) : (a))
#define N 1022
#define M 510
#define TMAX (100*50)
//#define DATA volatile unsigned int
#define DATA volatile double
//#define FIX 1024
#define FIX 1
#define SVM_TYPE SVM_STRONG
//#define SVM_TYPE SVM_LAZYRELEASE
static inline double pow(double a, int b)
{
double base = a;
int i;
for (i = 1; i < b; ++i)
a *= base;
return a;
}
int laplace(void *arg)
{
//char* argv[] = {"/bin/laplace", "192.168.4.254", "12301", NULL};
//int argc = 3;
#ifdef _USE_GFX
uint32_t ret;
#endif
int t;
int i, I, j, J;
int my_rank;
int num_ranks;
int n;
int m;
DATA **NewValues;
DATA **OldValues;
DATA **tmp;
char **BufValues;
uint64_t start, end;
my_rank = RCCE_IAM;
num_ranks = RCCE_NP;
#ifdef _USE_GFX
kprintf("Laplace calls gfx_init\n");
ret = GFX_init("192.168.4.254" /*&argc */ , "5000" /*&argv */ , my_rank);
kprintf("gfx_init: %d\n", ret);
#endif
m = M;
J = 0;
n = N / num_ranks;
I = n * my_rank;
if (my_rank == num_ranks - 1)
n += N % num_ranks;
kprintf("(%d of %d) %d x %d / offsets: %d, %d / (%d x %d)\n", my_rank, num_ranks, N, M, I, J, n, m);
#ifdef _USE_GFX
if (my_rank == 0) {
for (i = 0; i < 256; i++) {
//set color index, r, g, b
if (i < 64)
GFX_set_rgb(i, 0, i * 256 / 64, 255);
else if (i < 128)
GFX_set_rgb(i, 0, 255, 255 - ((i - 64) * 256 / 64));
else if (i < 192)
GFX_set_rgb(i, (i - 128) * 256 / 64, 255, 0);
else if (i < 256)
GFX_set_rgb(i, 255, 255 - ((i - 192) * 256 / 64), 0);
}
// TODO: move draw area to center
//GFX_set_xy(150, 150);
GFX_set_hd(N, 0);
}
#endif
NewValues = (volatile DATA **)kmalloc((N + 2) * sizeof(DATA *));
#ifdef SVM_TYPE
NewValues[0] = (DATA *) svm_malloc((N + 2) * (M + 2) * sizeof(DATA), SVM_TYPE);
#else
NewValues[0] = (DATA *) kmalloc((N + 2) * (M + 2) * sizeof(DATA));
#endif
OldValues = (volatile DATA **)kmalloc((N + 2) * sizeof(DATA *));
#ifdef SVM_TYPE
OldValues[0] = (DATA *) svm_malloc((N + 2) * (M + 2) * sizeof(DATA), SVM_TYPE);
#else
OldValues[0] = (DATA *) kmalloc((N + 2) * (M + 2) * sizeof(DATA));
#endif
for (i = 1; i < N + 2; i++) {
NewValues[i] = NewValues[i - 1] + (M + 2);
OldValues[i] = OldValues[i - 1] + (M + 2);
}
BufValues = (char **)kmalloc((N) * sizeof(char *));
BufValues[0] = (char *)kmalloc((N) * (M) * sizeof(char));
for (i = 1; i < N; i++) {
BufValues[i] = BufValues[i - 1] + (M);
}
#ifdef SVM_TYPE
svm_barrier(SVM_TYPE);
#endif
kprintf("(%d) Memory allocated!\n", my_rank);
//while (1)
{
int height = N + 2;
int width = M + 2;
if (my_rank == 0) {
for (j = 0; j < m + 2; j++) {
double X = (((double)(J+j) / (double)width) * 5.0) - 2.5;
double Y = 0.0;
double Z = 0.0;
Z = pow((4 - (X + 1) * (X + 1) - 4 * Y * Y), 2) + pow(1.2 * (1 - X), 3) - 10;
if (Z < 0.0)
Z = 1.0;
else if (Z > 0.0)
Z = 0.0;
OldValues[0][J+j] = NewValues[0][J+j] = (DATA) ((Z) * 255.0) * FIX;
}
}
for (i = 1; i < n+1; i++) {
for (j = 0; j < m + 2; j++) {
double X = (((double)(J+j) / (double)width) * 5.0) - 2.5;
double Y = (((double)(I+i) / (double)height) * 5.0) - 2.5;
double Z = 0.0;
Z = pow((4 - (X + 1) * (X + 1) - 4 * Y * Y), 2) + pow(1.2 * (1 - X), 3) - 10;
if (Z < 0.0)
Z = 1.0;
else if (Z > 0.0)
Z = 0.0;
OldValues[I+i][J+j] = NewValues[I+i][J+j] = (DATA) ((Z) * 255.0) * FIX;
}
}
if (my_rank == num_ranks - 1) {
for (j = 0; j < m + 2; j++) {
double X = (((double)(J+j) / (double)width) * 5.0) - 2.5;
double Y = (((double)(I+n+1) / (double)height) * 5.0) - 2.5;
double Z = 0.0;
Z = pow((4 - (X + 1) * (X + 1) - 4 * Y * Y), 2) + pow(1.2 * (1 - X), 3) - 10;
if (Z < 0.0)
Z = 1.0;
else if (Z > 0.0)
Z = 0.0;
OldValues[I+n+1][J+j] = NewValues[I+n+1][J+j] = (DATA) ((Z) * 255.0) * FIX;
}
}
#ifdef SVM_TYPE
svm_barrier(SVM_TYPE);
#endif
kprintf("(%d) Arrays initialized!\n", my_rank);
start = rdtsc();
// START ITERATIONS LOOP
for (t = 0; t < TMAX; t++) {
//kprintf("(%d): o:%u n:%u \n",my_rank,(unsigned int)(OldValues[I+1][J+1]), (unsigned int)(NewValues[I+1][J+1]) );
//kprintf("(%d): t: %u\n", my_rank, t);
// over all collumns
for (i = 1; i < n + 1; i++) {
// over all rows
for (j = 1; j < m + 1; j++) {
NewValues[I + i][J + j] =
(OldValues[I + i - 1][J + j] +
OldValues[I + i + 1][J + j] +
OldValues[I + i][J + j - 1] +
OldValues[I + i][J + j + 1]) / 4;
}
}
tmp = NewValues;
NewValues = OldValues;
OldValues = tmp;
#ifdef SVM_TYPE
svm_barrier(SVM_TYPE);
#endif
#ifdef _USE_GFX
if ((my_rank == 0) && (t % 50 == 0)) {
int diff, res = 0;
for (i = 1; i < N + 1; i++) {
for (j = 1; j < M + 1; j++) {
diff = ABS(NewValues[i][j] - OldValues[i][j]);
if (diff > res)
res = diff;
BufValues[i - 1][j - 1] = (unsigned char)(NewValues[i][j] / FIX);
//GFX_draw_pixel(150+j, 150+my_rank*n+i, (unsigned char)NewValues[i+1][j+1]);
//GFX_update();
}
}
kprintf("Graphic UPDATE! (t=%d) residual:%u \n", t, res);
GFX_draw_data((char *)(BufValues[0]), (N) * (M));
GFX_update();
}
#ifdef SVM_TYPE
svm_barrier(SVM_TYPE);
#endif
#endif
// END ITERATIONS LOOP
}
#ifdef SVM_TYPE
svm_barrier(SVM_TYPE);
#endif
end = rdtsc();
kprintf("Calculation time: %llu ms (%llu ticks)\n", (end-start)/(1000ULL*get_cpu_frequency()), end-start);
#ifdef SVM_TYPE
svm_statistics();
#endif
}
kprintf("(%d) Algorithm completed!\n", my_rank);
// TODO: Freeing memory regions
#ifdef _USE_GFX
gfx_finalize();
#endif
return 0;
}
#endif