This is my attempt to code the classical smoothing pixel average algorithm in MPI. I almost got it working but something weird happens with the halo exchange as can see the lines right in the edges. I can't seem to find the bug. Am I properly exchanging halos? What section of the final array should I gather?
https://pastebin.com/4rtFnSJ5
int next = rank + 1;
int prev = rank - 1;
if (next >= size) {
next = MPI_PROC_NULL;
}
if (prev < 0) {
prev = MPI_PROC_NULL;
}
int rows = y / px;
int cols = x;
int d = 1;
for (int iter = 0; iter < TotalIter; iter++) {
for (int i = 0; i < rows + 2; i++)
for (int j = 0; j < cols + 2; j++)
for (int k = 0; k < rgb; k++)
new[i][j * rgb + k] = 0;
for (int i = 1; i < rows + 1; i++) {
int iMin = -min(d, i - 1);
int iMax = min(d, (rows + 1 - i - 1));
for (int j = 1; j < cols + 1; j++) {
int jMin = -min(d, j - 1);
int iMax = min(d, (cols + 1 - j - 1));
int counter = 0;
for (int p = iMin; p <= iMax; p++)
for (int q = jMin; q <= jMax; q++) {
counter = counter + 1;
for (int k = 0; k < rgb; k++) {
new[i][j * rgb + k] += old[i + p][(j + q) * rgb + k];
}
}
for (int k = 0; k < rgb; k++) {
new[i][j * rgb + k] -= old[i][j * rgb + k];
new[i][j * rgb + k] /= (counter - 1);
}
}
}
for (int i = 2; i < rows; i++)
for (int j = 2; j < cols; j++)
for (int k = 0; k < rgb; k++) {
old[i][j * rgb + k] = new[i][j * rgb + k];
}
MPI_Sendrecv(&old[rows][1], cols * rgb, MPI_INT, next, 1, &old[0][1],
cols * rgb, MPI_INT, prev, 1, MPI_COMM_WORLD, &status);
MPI_Sendrecv(&old[1][1], cols * rgb, MPI_INT, prev, 2, &old[rows + 1][1],
cols * rgb, MPI_INT, next, 2, MPI_COMM_WORLD, &status);
}
for (int i = 1; i< rows+1; i++)
for (int j = 1; j< cols+1; j++)
for (int k = 0; k< rgb; k++) {
buf[i-1][(j-1)*rgb+k] = old[i][j*rgb+k] ;
}
MPI_Gather(&buf[0][0], rows *cols *rgb, MPI_INT, &Finalbuffer[0][0],
rows *cols *rgb, MPI_INT, 0, MPI_COMM_WORLD);
The output looks like this when run on 8 MPI processes. I can clearly see delimiting lines. For that reason I thought I was not doing halo exchanges properly.
OK, so there are a bunch of issues here.
First, your code could only ever work with d=1 since you only swap halos of depth 1. If you want to process neighbours of distance d, you need to swap halos of depth d.
Second, you do the first halo swap after your first sweep through the arrays so you are reading junk halo data on iteration 1 - you need to do a halo swap before you start processing your arrays.
Third, when you copy back new to old you start from index 2 : you need to include all the pixels from 1 to lrows and 1 to lcols.
Finally, your logic of Imin, Imax etc seems wrong. You don't want to truncate the range at the edges in the parallel program - you need to go off the edges to pick up the halo data. I just set Imin = -d, Imax = d etc.
With these fixes the code seems to run OK, i.e. there are no obvious halo effects, but it still gives different results on different numbers of processes.
PS I was also flattered to see you used the "arraymalloc2d" code from one of my own MPI examples - http://www.archer.ac.uk/training/course-material/2018/07/intro-epcc/exercises/cfd.tar.gz ; I'm glad to see that these training codes are proving useful to people!
I am trying to get some results by using Rcpp and this is the code.
#include <Rcpp.h>
#include <math.h>
using namespace Rcpp;
enter code here
// [[Rcpp::export]]
double compssr(NumericMatrix dist, NumericVector x, int n, int p) {
double ssr = 0; double del_sq = 0; double del_ij = 0;
int i, j, ip;
for (i = 0; i < n; i++) {
for (j = 0; j < i; j++) {
for (ip = 0; ip < p; ip++) {
del_sq = del_sq + (x(i, ip) - x(j, ip))*(x(i, ip) - x(j, ip));
if (i == j) del_sq = 0;
}
del_ij = sqrt(del_sq);
ssr = ssr + (dist(i, j) - del_ij)*(dist(i, j) - del_ij);
}}
return ssr;
}
NumericMatrix Scaling_X(NumericVector xbar, NumericMatrix x, double n, double p) {
NumericMatrix Sig_x(p, p);
int i, ii, ip, ip2;
for (ii = 0; ii < n; ii++) {
for (i = 0; i < p; i++) {
x(ii, i) = x(ii, i) - xbar(i);
}}
for (i = 0; i < n; i++) {
for (ip = 0; ip < p; ip++) {
for (ip2 = 0; ip2 < p; ip2++) {
Sig_x(ip, ip2) = Sig_x(ip, ip2) + x(i, ip)*x(i, ip2);
}}}
for (i = 0; i < Sig_x.ncol(); i++) {
for (ii = 0; ii < Sig_x.nrow(); ii++) {
Sig_x(i, ii) = Sig_x(i, ii) / n;
}}
return Sig_x;
}
In fact there are some more functions and the file name of this code is "test.cpp"
And I called this file in R by using
sourceCpp("test.cpp")
There was no error and I could use the function "compssr" the first function(return type: double)
But I couldn't call the function Scaling_X
Is there any error in my code?
I made other functions and I could use the function with return type double, but I couldn't use others(NumericMatrix, NumericVector, List)
You are missing the
// [[Rcpp::export]]
in front of function Scaling_X so the compileAttributes() function does as it has been told: compile both functions, make just one available.
I have tried following code but it writes in vertical way.How can i add 2d array into my listbox
for (int i = 0; i < test.GetLength(0); i++)
{
for (int j = 0; j < test.GetLength(1); j++)
{
ListBox3.Items.Add("-" + test[i, j].ToString());
}
ListBox3.Items.Add("\n");
}
}
This may help you from what I understand from your query;
string listboxstr = "";
for (int i = 0; i < test.GetLength(0); i++)
{
listboxstr = "" + test[i, 0].ToString();
for (int j = 1; j < test.GetLength(1); j++)
{
listboxstr +="-" + test[i, j].ToString();
}
ListBox3.Items.Add(listboxstr);
ListBox3.Items.Add("\n");
}
}
Currently I'm trying to replicate this wonderful project https://www.youtube.com/watch?v=u8pwmzUVx48, though with more minimum hardware, in which for the classification i'm using a neural network embbeded inside the arduino uno which had been trained offline in more stronger PC. The code of the classifier is here
#include <math.h>
#include <Wire.h>
double dataMagnitude[100];
double feature[7];
double feat_hid[10];
double output[4];
int classi;
const double w_hid[8][10] =
{
{18.9336670380822,11.9186055569093,-5.40114594311576,-21.1410711100689,-49.7798510124792,-14.8215222433047,-34.7308138535581,118.348601654702,-13.6275407707706,-11.6090487951753},
{-21.4994463865001,72.0672467700052,4.05328299052883,21.4875491464005,51.1604296852446,-15.8459578543758,6.30350750703905,-152.565733734759,12.8648040583067,13.8199895673734},
{8.66214515599865,-200.488705071393,-5.86973559011113,-23.4805286444925,-1.11016147795671,-3.04686605995311,-93.4143749063794,-73.8925691072615,-6.18427236042285,-10.9872535411407},
{-12.317892447947,-37.2154526807162,3.83978412266769,2.12866508710205,-11.9740446238331,10.2198116665101,41.9369083083022,63.2036147993661,1.40768362243561,15.4978881385563},
{7.58319670243546,161.895072542918,-2.3654701067923,1.91708846557259,-2.87224127392426,-16.5850302581614,45.2372430254377,34.255971511768,-2.30234070310014,-7.8952356779332},
{0.603971580989218,128.0244079393,0.628535912033608,-1.25788426737745,-0.204480047424961,-41.3372322514891,3.26860448943873,4.163893213914,0.443532051478394,-0.276136697942473},
{-3.63944154925129,18.3802540188974,0.975095285922393,-0.326187652485656,1.25521855841132,39.4877166809573,-15.3542772116519,-14.9546824078715,0.965532742621277,3.72386985716534},
{5.93321854314305,12.673690719929,-3.36580252980446,-21.2089241183081,-10.8980644878121,-7.29095431091201,-30.2240843969778,-2.48980394834853,-5.4167647620581,-5.68671825319015}
}, w_out[11][4] =
{
{1.07887052819228,-21.9615926704441,105.450147012522,-84.5674248703326},
{0.0344508533215184,0.551350792323934,-0.96380329372866,0.37800164808339},
{-99.251397621058,23.1671754381478,7.53147169676884,68.5527504861813},
{-5.0354869957171,4.36918523413481,0.408725687040089,0.257576074543764},
{-27.4478368365984,7.00659524306471,1.74370945871769,18.6975321348269},
{-0.213736004615516,-0.784795805217531,0.0732416484342244,0.925290161399087},
{8.62052547929066,-45.9408034639393,116.959261953552,-79.6389839689755},
{-8.5317661802465,45.4251911929737,-117.146523754862,80.2530987422069},
{127.053878005091,-29.4397580015468,-9.33919798608733,-88.2749220175082},
{1.11869995358251,-21.5111648695486,105.002356379838,-84.6098914639344},
{-5.81786935588552,3.78305066207264,0.11556429335063,-0.0807455995360207}
};
double S, Sig, Sigma, Sigma1, Sigma2, MAV, RMS, VAR, SDT, WL, ZC, SSC, Xn, accum, accumi;
char analogpin = 0, N=100;
void setup()
{
/* add setup code here */
Serial.begin(9600);
Wire.begin();
}
void loop()
{
do{
//data acqusition
for( int i = 0; i<100;i++)
{
Xn = (analogRead(analogpin))-510;
dataMagnitude[i]=Xn;
delayMicroseconds(830);
// Serial.println(dataMagnitude[i]);
}
S = 0;
for (size_t i = 0; i < N; i++)
{
S = S + dataMagnitude[i];
}
Sig = 0;
Sigma = 0;
Sigma1 = 0;
Sigma2 = 0;
for (size_t i = 0; i < N; i++)
{
Sig = Sig + abs(dataMagnitude[i]);
Sigma = Sigma + pow(dataMagnitude[i], 2);
Sigma1 = Sigma1 + pow((dataMagnitude[i] - S / N), 2);
}
for (size_t i = 0; i < N - 1; i++)
{
Sigma2 = Sigma2 + abs(dataMagnitude[i + 1] - dataMagnitude[i]);
}
//featureextract
MAV = (((1 / (double)N)*Sig-27.67)*2/(272.02-27.67))-1;
RMS = (sqrt((1 / (double)N)*Sigma)-34.91002721)*2/(284.1419012-34.91002721)-1;
VAR = (((1 / (double)(N))*Sigma1)-698.4139)*2/(52178.5691-698.4139)-1;
SDT = (sqrt((1 / (double)(N)) * Sigma1)-26.42752164)*2/(228.4262881-26.42752164)-1;
WL = (Sigma2-1621)*2/(11273-1621)-1;
//ZC = 0;
for (size_t i = 0; i < N - 1; i++)
{
if (dataMagnitude[i] == 0 && dataMagnitude[i] != dataMagnitude[i + 1])
{
ZC++;
}
}
ZC = (ZC-0)*2/(39-0)-1;
//SSC = 0;
for (size_t i = 0; i < N - 2; i++)
{
if (dataMagnitude[i]>dataMagnitude[i + 1] && dataMagnitude[i + 1]<dataMagnitude[i + 2])
{
SSC++;
}
else if (dataMagnitude[i]<dataMagnitude[i + 1] && dataMagnitude[i + 1]>dataMagnitude[i + 2])
{
SSC++;
}
}
SSC = (SSC-48)*2/(78-48)-1;
double feature[] = { MAV, RMS, VAR, SDT, WL, ZC, SSC };
//neural network construction
//first-hidden layer
for (int i = 0; i < 10; i++)
{
accum = w_hid[7][i];
for (int j = 0; j < 7; j++)
{
accum += (feature[j] * w_hid[j][i]);
}
feat_hid[i] = tanh(accum);
}
for (int i = 0; i < 4; i++)
{
accumi = w_out[10][i];
for (int j = 0; j < 10; j++)
{
accumi += (feat_hid[j] * w_out[j][i]);
}
output[i] = round(accumi);
}
//Classify the output
if (output[0] == 1 && output[1] < 1 && output[2] < 1 && output[3] < 1)
{
classi = 1;
}
else if (output[0] < 1 && output[1] == 1 && output[2] < 1 && output[3] < 1)
{
classi = 2;
}
else if (output[0] < 1 && output[1] < 1 && output[2] == 1 && output[3] < 1)
{
classi = 3;
}
else if (output[0] < 1 && output[1] < 1 && output[2] < 1 && output[3] == 1)
{
classi = 4;
}
else
{
classi = 0;
}
Wire.beginTransmission(5);
Wire.write(classi);
//Wire.write(int(output[2]));
Wire.endTransmission();
Serial.println("wew");
Serial.println(output[0]);
Serial.println(output[1]);
Serial.println(output[2]);
Serial.println(output[3]);
//Serial.println(classi);
//Serial.println(feature[1]);
//Serial.println(feature[2]);
//Serial.println(feature[3]);
//Serial.println(feature[4]);
//Serial.println(feature[5]);
//Serial.println(feature[6]);
for (size_t i = 0; i < 10; i++)
{
feat_hid[i] = 0;
}
for (size_t i = 0; i < 4; i++)
{
output[i] = 0;
}
}while(analogRead(analogpin)>0);
}
But the real time implementation is rather dissatisfying, in which the output always mismatched, though by offline implementation is quite better.
My assumption is that the data capturing when online is rather bad, or maybe because any other things?
Thanks for any feedback
How did you train the network offline?
If you have used Matlab to train the network (i.e. to identify the weight and bias values) and then implement the same network on Arduino.
In such case we have problems with number precision. Matlab by default works on 64 bit precision whereas Arduino works on 32 bit.
Difference in the way the numbers are represented creates the Error.
Hey I am trying to multiply two dimensional arrays and I am confused. I have this code, but It Doesn't seem to work..
class MatrixMultiply {
public static void main(String[] args) {
int array[][] = { {1,2,-2,0}, {-3,4,7,2}, {6,0,3,1} };
int array1[][] = { {-1,3}, {0,9}, {1,-11}, {4,-5} };
int array2[][] = new int[2][3];
int x= array.length;
int y= array1.length;
for(int i = 0; i < x; i++) {
for(int j = 0; j < y-1; j++) {
for(int k = 0; k < y; k++){
array2[i][j] += array[i][k]*array1[k][j];
}
}
}
System.out.println("After we multiply the two arrays: ");
for(int i = 0; i < x; i++) {
for(int j = 0; j < y-1; j++) {
System.out.print(" "+array2[i][j]);
}
System.out.println();
}
}
}
modify your loop that multiplies the array.
for (int i = 0; i < x-1; i++) {
for (int j = 0; j < array1[0].length; j++) {
for (int k = 0; k < array[0].length; k++) {
array2[i][j] += array[i][k] * array1[k][j];
}
}
}