I'm trying to do some stencil computation using Halide. So assuming a basic 5 point 2D stencil, to evaluate some value at cell i,j I need the values of i-1,j i-2,j, i+1,j i+2,j. Now the way this works in C++ is that I have a for statement:
for(int i = 2; i < max_i - 2; i++)
for(int j = 2; j < max_j - 2; j++)
Calculate out = some_function_of(in(i,j), in(i-1,j), in(i-2,j), in(i+1,j), in(i+2,j))
Now I'm trying to do the same thing with Halide. so I have a Buffer called in which has the same value as my input array in the C++ code. And I have a Func called out:
out(i,j) = select(i >= 2 && j >= 2, some_function_of(in(i,j), in(i-1,j), in(i-2,j), in(i+1,j), in(i+2,j)) ,0.0f)
When I run this code I get the following error:
Error:
Input buffer b0 is accessed at -1, which is before the min (0) in dimension 0
Aborted (core dumped)
From my understanding, the reason for this error is that the select statement evaluates both statements so eventhough I don't want to calculate anything for i and j values less than two, the function is evaluated at i = 0 and j = 0 and thus the invalid address access.
So is there anyway to do this in Halide? Are there any other equivalents for if/else statements?
Using a boundary condition will do what you want:
Func unbounded;
unbounded(i, j,) = some_function_of(in(i,j), in(i-1,j), in(i-2,j), in(i+1,j), in(i+2,j));
out(i, j) = BoundaryConditions::constant_exterior(unbounded, 0.0f, 2, width - 4, 2, height - 4)(i, j);
I believe you can use "Expr()" instead of "width - 4" or "height - 4" if you want the maximum unbounded.
The use if BoundaryConditions functions allows hinting the compiler which direction of the if/else construct is more likely.
Related
I am trying to convert a recursion into a mathematical formula. The code snippet (c++) below is a simplified variant. The values look like an exponential function, however I am trying to find a closed form. For example, rec(8, 6) is 1287. As an assumption, I first assumed 6 to be constant and tried to find an exponential function for rec(?, 6). However, these results were extremely inaccurate. Does anyone have an idea how I could achieve a closed function?
Many thanks
int rec(const int a, const int b, const int c = 0, const int d = 0)
{
int result = 0;
if (d == a)
++result;
else
for (int i = 0; c + i < b; ++i)
result += rec(a, b, c + i, d + 1);
return result;
}
There is no universal method of converting a recursive function to a mathematical, closed function. In your case the answer is the number of "b-1" combinations from an "a"-element set, that is, a!/((a-b+1)!(b-1)!).
Proof: Your rec is equivalent to
int rec(const int a, const int b)
{
if (0 == a)
return 1;
int result = 0;
for (int i = 0; i < b; ++i)
result += rec(a - 1, b - i);
return result;
}
because all that matters is a-d and b-c.
If a==0, rec returns 1
If a>0, it returns the sum of rec(a-1, i) where i is in (0, b). This is true and only true for the combinations. If you ask me to prove that, I will, but the plain text format is not good for mathematical proofs
Edit: A general idea.: print all rec(i,j) as a table and try to spot the rule by looking at the table. I did:
for (int i = 0; i != 10 ; ++i){
for (int j = 0; j != 10; ++j){
cout << rec(i, j) << "\t";
}
cout << endl;
}
In this way I spotted that it is the Pascals_triangle
I will give a hint how you could have guessed the result yourself, with the stress on guess.
Take the sequence for rec(i, 6), i = 0,...,10. This is the sequence that you had already investigated. The answer is:
1 6 21 56 126 252 462 792 1287 2002
Now, insert it into Google (I don't know if other search engines can do the trick; Google certainly can). The first result should point you to this famous online encyclopedia:
https://oeis.org/A000389
This the Online Encyclopedia of Integer Sequences! Now, read the description:
A000389 Binomial coefficients C(n,5).
You may be not familiar with the C(*,*) notation, but you can easily understatand its "Binomial coefficient" description.
You certainly notice the relation between 6 in your function and 5 in the answer formula, but to be sure you can repeat your experiment for several other numbers other than 6.
The next step is to see how the A000389 sequence looks like:
0, 0, 0, 0, 0, 1, 6, 21, 56, 126, 252, 462, 792, 1287, 2002, ...
Well, C(i,j) is undefined (or zero, depending on the convention) if i < j. Aha! A000389 is this:
C(0,5) = 0, C(1,5) = 0, ... , C(4,5) = 0, C(5,5) = 1, C(6,5) = 6,...
This is your sequence if you started from the term of index 5, if we start counting from 0.
res(0,6) = C(5,5), res(1,6) = C(6,5),..., res(k, 6) = C(5+k, 5)
You can generalize it to
res(k, j) = C(k + j - 1, j -1)
and then start thinking how to prove it in a mathematically strict way. The usual method is by mathematical induction - I'll skip it.
This final result is already given by #Botond_Horwath, I just show to you the magic of Google search engine + the OEIS website. (If you know the latter, the former is redundant).
Like any normal C++ programmer, when I type this code...
for (int m = 0; m < 3; m++){
for (int n = 0; n < 3; n++){
if (A[m].substr(size,location) == B[n].substr(size,location)){
return false;
}
}
}
I expect the first value of m to be 0 in my iteration. (because I literally declared it as having a value of 0) However, my program was acting a tad funky, so I decided to look at it in the debugger. Interestingly, rather than having a starting value of 0, C++ decided that m should have a starting value of 32767.
Could someone explain to my why and how this could possibly happen?
Ah, templatetypedef was right. Once I stepped over to the next breakpoint its value was initialized. Thanks guys!
Ok some background
I have been working on this project, which I had started back in college, (no longer in school but want to expand on it to help me improve my understanding of C++). I digress... The problem is to find the Best path through a matrix. I generate a matrix filled with a set integer value lets say 9. I then create a path along the outer edge (Row 0, Col length-1) so that all values along it are 1.
The goal is that my program will run through all the possible paths and determine the best path. To simplify the problem I decide to just calculate the path SUM and then compare that to what the SUM computed by the application.
(The title is miss leading S=single-thread P=multi-threads)
OK so to my question.
In one section the algorithm does some simple bit-wise shifts to come up with the bounds for iteration. My question is how exactly do these shifts work so that the entire matrix (or MxN array) is completely traversed?
void AltitudeMapPath::bestPath(unsigned int threadCount, unsigned int threadIndex) {
unsigned int tempPathCode;
unsigned int toPathSum, toRow, toCol;
unsigned int fromPathSum, fromRow, fromCol;
Coordinates startCoord, endCoord, toCoord, fromCoord;
// To and From split matrix in half along the diagonal
unsigned int currentPathCode = threadIndex;
unsigned int maxPathCode = ((unsigned int)1 << (numRows - 1));
while (currentPathCode < maxPathCode) {
tempPathCode = currentPathCode;
// Setup to path iteration
startCoord = pathedMap(0, 0);
toPathSum = startCoord.z;
toRow = 0;
toCol = 0;
// Setup from path iteration
endCoord = pathedMap(numRows - 1, numCols - 1);
fromPathSum = endCoord.z;
fromRow = numRows - 1;
fromCol = numCols - 1;
for (unsigned int index = 0; index < numRows - 1; index++) {
if (tempPathCode % 2 == 0) {
toCol++;
fromCol--;
}
else {
toRow++;
fromRow--;
}
toCoord = pathedMap(toRow, toCol);
toPathSum += toCoord.z;
fromCoord = pathedMap(fromRow, fromCol);
fromPathSum += fromCoord.z;
tempPathCode = tempPathCode >> 1;
}
if (toPathSum < bestToPathSum[threadIndex][toRow]) {
bestToPathSum[threadIndex][toRow] = toPathSum;
bestToPathCode[threadIndex][toRow] = currentPathCode;
}
if (fromPathSum < bestFromPathSum[threadIndex][fromRow]) {
bestFromPathSum[threadIndex][fromRow] = fromPathSum;
bestFromPathCode[threadIndex][fromRow] = currentPathCode;
}
currentPathCode += threadCount;
}
}
I simplified the code since all the extra stuff just detracts from the question. Also if people are wondering I wrote most of the application but this idea of using the bit-wise operators was given to me by my past instructor.
Edit:
I added the entire algorithm for which each thread executes on. The entire project is still a work a progress but here is the source code for the whole thing if any one is interested [GITHUB]
A right bit shift is equivalent to dividing by 2 to the power of the number of bits shifted. IE 1 >> 2 = 1 / (2 ^ 2) = 1 / 4
A left bit shift is equivalent to multiplying by 2 to the power of the number of bits shifted. IE 1 << 2 = 1 * 2 ^ 2 = 1 * 4
I'm not entirely sure what that algorithm does and why it needs to multiply by 2^ (num rows - 1) and then progressively divide by 2.
for (short i = 1; i < 5; i++)
for (j = 0; j > 0; j--)
cout << i << "\t";
Anybody please answer the above code.. i am getting continuous zero why is it so please explain
First off, you need to declare the variable j somewhere. Assuming you have declared j somewhere else in the program, this program as you have written it here will actually print nothing out.
Since j is set to start at 0, and 0 is not greater than 0, the
cout<<i<<"\t";
line will never actually be run. If you could provide more of your code we may be able to answer your question better. You could try setting j to start at 1 if you want it to actually print out i.
Link to Online IDE running the program
On executing the program, there is no output.
for(short i=1;i<5;i++)
This statement declares and initializes the variable i to 1, checks if it is less than 5 and then moves on to the next statement
for(j=0;j>0;j--)
This statement initializes j to 0 (Note that j has to be declared previously), and then checks if j is greater than 0. As j isn't greater than 0, it doesn't move on to the next statement, i.e. cout<<i<<"\t"; and continues the previous loop, the loop with the variable i.
The i- loop runs 4 times, and since anything isn't actually printed to the screen, you don't get any output.
First this code won't compile as you have not defined j. After you do that, it wont print anything as j is never greater than 0.
#include <iostream>
int main()
{
for(short i=1;i<5;i++)
for(short j=0;j>0;j--)
std::cout<<i<<"\t";
return 0;
}
for (j = 0; j > 0; j--)
This is a zero iteration loop. Initializes j to 0 checks if j is greater than 0.
1) If j=0, the loop undergoes 0 iterations and hence no output.
2) If j=5, you get each of the numbers from 1 to 5 printed 5 times as output.
1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5
I have this very weird issue going on. The function you will see in a moment is supposed to ensure that all elements (chars) in a 2D array are at there utmost position, that is, there is no empty space above any of the characters. For instance a board could look like this:
1 X * * X ^
2 * X ^ *
3 o o * X ^
4 o ^ X X X
5 ^ * X * ^
1 2 3 4 5
And there is an issue at (2,1) because there is an empty space above a non empty space.
My function does the sorting correctly but it deletes any character in the bottom row that has an empty space above it. I cannot, for the life of me, figure out why. Here is my sort function.
int bb_float_one_step(BBoard board){
int i,j;
for (i = 0; i < board->rows; i++){
for (j = 0; j < board->cols; j++){
if (board->boardDim[i][j] == None && (board->boardDim[i + 1][j] != None && i + 1 <= board->rows)){
char tmp = board->boardDim[i + 1][j];
board->boardDim[i + 1][j] = board->boardDim[i][j];
board->boardDim[i][j] = tmp;
}
}
}
for (i = 0; i < board->rows; i++){
for (j = 0; j < board->cols; j++){
printf("%c",board->boardDim[i][j]);}printf("\n");}
}
Below Is a picture of the full sequence, The Program prints a board. The user is asked to select a region to 'pop.' A function then replaces all the characters that are connected with a blank space. Then in the last portion of the picture you can see how the characters are deleted. The board that doesn't have a border is there because I was using it to check if the characters actually were deleted or not.
Thank you in advanced for 1, reading this whole post, and 2, any help you can give.
Since you are comparing current row with next row you should use for(i = 0; i < board->rows-1; i++)
Then in your complex if statement, get rid of && i <= board->rows. That should have been a less-than anyway, not less-than-or-equals. You're going out of bounds and getting garbage in your array.
You are checking the row beyond the maximum number of rows.
(board->boardDim[i + 1][j] != None && i + 1 <= board->rows)
That memory is not guaranteed to be 0. If it is not 0, your function will swap it in. If it is not human readable, printf won't print anything for it thereby shifting the | to the left.