Frama-C slice: parallelizable loop - frama-c

I am trying to perform a backward slicing of an array element at specific position. I tried two different source codes. The first one is (first.c):
const int in_array[5][5]={
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
};
int out_array[5][5];
int main(unsigned int x, unsigned int y)
{
int res;
int i;
int j;
for(i=0; i<5; i++){
for(j=0; j<5; j++){
out_array[i][j]=i*j*in_array[i][j];
}
}
res = out_array[x][y];
return res;
}
I run the command:
frama-c-gui -slevel 10 -val -slice-return main file.c
and get the following generated code:
int main(unsigned int x, unsigned int y)
{
int res;
int i;
int j;
i = 0;
while (i < 5) {
j = 0;
while (j < 5){
out_array[i][j] = (i * j) * in_array[i][i];
j ++;
}
i ++;
}
res = out_array[x][y];
return res;
}
This seems to be ok, since the x and y are not defined, so the "res" can be at any position in the out_array. I tried then with the following code:
const int in_array[5][5]={
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
};
int out_array[5][5];
int main(void)
{
int res;
int i;
int j;
for(i=0; i<5; i++){
for(j=0; j<5; j++){
out_array[i][j]=i*j*in_array[i][j];
}
}
res = out_array[3][3];
return res;
}
The result given was exactly the same. However, since I am explicitly looking for a specific position inside the array, and the loops are independent (parallelizable), I would expect the output to be something like this:
int main(void)
{
int res;
int i;
int j;
i = 3;
j = 3;
out_array[i][j]=(i * j) * in_array[i][j];
res = out_array[3][3];
}
I am not sure if is it clear from the examples. What I want to do is to identify, for a given array position, which statements impact its final result.
Thanks in advance for any support.

You obtain "the statements which impact the final result". The issue is that not all loop iterations are useful, but there is no way for the slicing to remove a statement to the code in its current form. If you perform syntactic loop unrolling, with -ulevel 5, then you will each loop iteration is individualized, and slicing can decide for each of them whether it is to be included in the slice or not. In the end, frama-c-gui -ulevel 5 -slice-return main loop.c gives you the following code
int main(void)
{
int res;
int i;
int j;
i = 0;
i ++;
i ++;
i ++;
j = 0;
j ++;
j ++;
j ++;
out_array[i][j] = (i * j) * in_array[i][j];
res = out_array[3][3];
return res;
}
which is indeed the minimal set of instructions needed to compute the value of out_array[3][3].
Of course whether -ulevel n scales up to very high values of n is another question.

Related

How to write Nested Loop in Kernel side OpenCL

I'm a beginner in OpenCL. I'm trying to implement an OpenCL application.I have a doubt that how to write opencl kernel code . i have given a original c code.
Question :- help me to change that given c code into opencl kernel code?.
ORIGINAL C CODE:
int i, j;
// initialization of indexes
for (i = 0; i<n; i++)
Index[i] = i;
// Bubble sort
for (i = 0; i<n - 1; i++)
{
for (j = i + 1; j<n; j++)
{
if (I[i] > I[j])
{
double z = I[i]; // exchange attractiveness
I[i] = I[j];
I[j] = z;
z = f[i]; // exchange fitness
f[i] = f[j];
f[j] = z;
int k = Index[i]; // exchange indexes
Index[i] = Index[j];
Index[j] = k;
}
}
}
Example for 4096 element arrays(alternate bubble1 and bubble2 at least 2048 times--->4096(N) kernel executions ):
index init on host side since its just assignment.
Auxiliary functions:
void swap2p(__private int * I,int i,int j)
{
int tmp=I[i];
I[i]=I[j];
I[j]=tmp;
}
void swap2g(__global int * I,int i,int j)
{
int tmp=I[i];
I[i]=I[j];
I[j]=tmp;
}
Alternating kernel-1:
__kernel void bubble1(__global int * I, __global int * f, __global int * Index){
int threadId=get_global_id(0);
__private int vals[2];
if(threadId*2+1<4096)
{
vals[0]=I[threadId*2];
vals[1]=I[threadId*2+1];
if(vals[0]>vals[1])
{
swap2p(vals,threadId*2,threadId*2+1);
swap2g(f,threadId*2,threadId*2+1);
swap2g(Index,threadId*2,threadId*2+1);
I[threadId*2]=vals[0];
I[threadId*2+1]=vals[1];
}
}
}
alternating kernel-2:
__kernel void bubble2(__global int * I){
int threadId=get_global_id(0);
__private int vals[2];
if(threadId*2+2<4096)
{
vals[0]=I[threadId*2+1];
vals[1]=I[threadId*2+2];
if(vals[0]>vals[1])
{
swap2p(vals,threadId*2+1,threadId*2+2);
swap2g(f,threadId*2+1,threadId*2+2);
swap2g(Index,threadId*2+1,threadId*2+2);
I[threadId*2+1]=vals[0];
I[threadId*2+2]=vals[1];
}
}
}
Global thread number: N/2 (2048)

Facing incorrect output while linking programs

I am having a trouble in calling the user defined functions in the main program, using unix. the program is executing only for the number generation in the main program. but when i call the predefined function . the output retrieved is incorrect. Can someone please correct me where i have done it wrong
My main program states as
#include <stdio.h>
#include <stdlib.h>
void sort1(int []);
int main(void) {
int array[100];
int i , j;
printf("ten random numbers in [1,1000]\n");
for (i = 1; i <= 10; i++)
{
generate random numbers
}
printf("The list of Hundred random numbers are \n");
for (j = 1; j <= 10; j++ )
{
//to print the random numbers
}
sort1(array);
return 0;
}
//this is my user defined function: sort1.c
include <stdio.h>
int sort1(int a[])
{
int array[100], i, d, swap, e=10;
// algortithm
}
}
printf("Sorted list in ascending order:\n");
for ( i= 0 ; i< e ; i++ )
printf("%d\n", array[i]);
}
I get the output as
ten random numbers in [1,1000]
The list of Hundred random numbers are
--This gives correct output
Sorted list in ascending order:
1
-1442229816
0
-1444472964
#include <stdio.h>
#include <stdlib.h>
void sort1(int []);
int main(void) {
int array[100];
int i;
printf("ten random numbers in [1,1000]\n");
for (i = 1; i <= 10; i++)
{
array[i] = rand()%1000 + 1;
}
printf("The list of Hundred random numbers are \n");
for (i = 1; i <= 10; i++ )
{
printf("Element[%d] = %d\n", i, array[i] );
}
//Up to here it's ok but you have set the values in the positions 1-10 of the array so keep consistent with it
sort1(array);
printf("Sorted list in ascending order:\n");
for ( i= 1 ; i<= 10 ; i++ )
printf("%d\n", array[i]);
return 0;
}
void sort1(int a[])
{
int i,swap,sorted=0;
while(sorted==0){ //flag to know if array is sorted 0 means not sorted.
sorted=1; // we set the flag to sorted at start of sweep
for (i= 1 ; i<= (10-1); i++) //sweep through array
{
if (a[i] > a[i+1]) //check if sorted
{
swap = a[i];
a[i] = a[i+1];
a[i+1] = swap;
sorted=0; //if not sorted set flag to 0 and swap
}
}
}
}
Main problems in your code:
1) array[100] is not initialized in sort1 function.
2) I do not understand your sorting algorithm but in any case you are checking for values of a[0] which are not initialized so take care of the array positions you use each time and be consistent with it.
3) function prototype does not match

Unhandled exception error with two dimensional array

This dynamic programming algorithm is returning unhandled exception error probably due to the two dimensional arrays that I am using for various (and very large) number of inputs. I can't seem to figure out the issue here. The complete program as follows:
// A Dynamic Programming based solution for 0-1 Knapsack problem
#include<stdio.h>
#include<stdlib.h>
#define MAX 10000
int size;
int Weight;
int p[MAX];
int w[MAX];
// A utility function that returns maximum of two integers
int maximum(int a, int b) { return (a > b) ? a : b; }
// Returns the maximum value that can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
int i, w;
int retVal;
int **K;
K = (int**)calloc(n+1, sizeof(int*));
for (i = 0; i < n + 1; ++i)
{
K[i] = (int*)calloc(W + 1, sizeof(int));
}
// Build table K[][] in bottom up manner
for (i = 0; i <= n; i++)
{
for (w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w] = maximum(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
retVal = K[n][W];
for (i = 0; i < size + 1; i++)
free(K[i]);
free(K);
return retVal;
}
int random_in_range(unsigned int min, unsigned int max)
{
int base_random = rand();
if (RAND_MAX == base_random) return random_in_range(min, max);
int range = max - min,
remainder = RAND_MAX % range,
bucket = RAND_MAX / range;
if (base_random < RAND_MAX - remainder) {
return min + base_random / bucket;
}
else {
return random_in_range(min, max);
}
}
int main()
{
srand(time(NULL));
int val = 0;
int i, j;
//each input set is contained in an array
int batch[] = { 10, 20, 30, 40, 50, 5000, 10000 };
int sizeOfBatch = sizeof(batch) / sizeof(batch[0]);
//algorithms are called per size of the input array
for (i = 0; i < sizeOfBatch; i++){
printf("\n");
//dynamic array allocation (variable length to avoid stack overflow
//calloc is used to avoid garbage values
int *p = (int*)calloc(batch[i], sizeof(int));
int *w = (int*)calloc(batch[i], sizeof(int));
for (j = 0; j < batch[i]; j++){
p[j] = random_in_range(1, 500);
w[j] = random_in_range(1, 100);
}
size = batch[i];
Weight = batch[i] * 25;
printf("| %d ", batch[i]);
printf(" %d", knapSack(Weight, w, p, size));
free(p);
free(w);
}
_getch();
return 0;
}
Change this:
for (i = 0; i < size + 1; i++)
free(K[i]);
free(K);
return K[size][Weight];
To this:
int retVal;
...
retVal = K[size][Weight];
for (i = 0; i < size + 1; i++)
free(K[i]);
free(K);
return retVal;

Spellcheck program using MPI

So, my assignment is to write a spell check program and then parallelize it using openMPI. My take was to load the words from a text file into my array called dict[] and this is used as my dictionary. Next, I get input from the user and then it's supposed go through the dictionary array and check whether the current word is within the threshold percentage, if it is, print it out. But I'm only supposed to print out a certain amount of words. My problem is, is that, my suggestions[] array, doesn't seem to fill up the way I need it to, and it gets a lot of blank spots in it, whereas, I thought at least, is that the way I wrote it, is to just fill it when a word is within threshold. So it shouldn't get any blanks in it until there are no more words being added. I think it's close to being finished but I can't seem to figure this part out. Any help is appreciated.
#include <stdio.h>
#include <mpi.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 30
#define max(x,y) (((x) > (y)) ? (x) : (y))
char *dict[50000];
char *suggestions[50000];
char enterWord[50];
char *myWord;
int wordsToPrint = 20;
int threshold = 40;
int i;
int words_added = 0;
int levenshtein(const char *word1, int len1, const char *word2, int len2){
int matrix[len1 + 1][len2 + 1];
int a;
for(a=0; a<= len1; a++){
matrix[a][0] = a;
}
for(a=0;a<=len2;a++){
matrix[0][a] = a;
}
for(a = 1; a <= len1; a++){
int j;
char c1;
c1 = word1[a-1];
for(j = 1; j <= len2; j++){
char c2;
c2 = word2[j-1];
if(c1 == c2){
matrix[a][j] = matrix[a-1][j-1];
}
else{
int delete, insert, substitute, minimum;
delete = matrix[a-1][j] +1;
insert = matrix[a][j-1] +1;
substitute = matrix[a-1][j-1] +1;
minimum = delete;
if(insert < minimum){
minimum = insert;
}
if(substitute < minimum){
minimum = substitute;
}
matrix[a][j] = minimum;
}//else
}//for
}//for
return matrix[len1][len2];
}//levenshtein
void prompt(){
printf("Enter word to search for: \n");
scanf("%s", &enterWord);
}
int p0_compute_output(int num_processes, char *word1){
int totalNumber = 0;
int k = 0;
int chunk = 50000 / num_processes;
for(i = 0; i < chunk; i++){
int minedits = levenshtein(word1, strlen(word1), dict[i], strlen(dict[i]));
int thresholdPercentage = (100 * minedits) / max(strlen(word1), strlen(dict[i]));
if(thresholdPercentage < threshold){
suggestions[totalNumber] = dict[i];
totalNumber = totalNumber + 1;
}
}//for
return totalNumber;
}//p0_compute_output
void p0_receive_output(int next_addition){
int num_to_add;
MPI_Comm comm;
MPI_Status status;
MPI_Recv(&num_to_add,1,MPI_INT,MPI_ANY_SOURCE, MPI_ANY_TAG,MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("--%d\n", num_to_add);
suggestions[next_addition] = dict[num_to_add];
next_addition = next_addition + 1;
}
void compute_output(int num_processes, int me, char *word1){
int chunk = 0;
int last_chunk = 0;
MPI_Comm comm;
if(50000 % num_processes == 0){
chunk = 50000 / num_processes;
last_chunk = chunk;
int start = me * chunk;
int end = me * chunk + chunk;
for(i = start; i < end;i++){
int minedits = levenshtein(word1, strlen(word1), dict[i], strlen(dict[i]));
int thresholdPercentage = (100 * minedits) / max(strlen(word1), strlen(dict[i]));
if(thresholdPercentage < threshold){
int number_to_send = i;
MPI_Send(&number_to_send, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
}
}
}
else{
chunk = 50000 / num_processes;
last_chunk = 50000 - ((num_processes - 1) * chunk);
if(me != num_processes){
int start = me * chunk;
int end = me * chunk + chunk;
for(i = start; i < end; i++){
int minedits = levenshtein(word1, strlen(word1), dict[i], strlen(dict[i]));
int thresholdPercentage = (100 * minedits) / max(strlen(word1), strlen(dict[i]));
if(thresholdPercentage < threshold){
int number_to_send = i;
MPI_Send(&number_to_send, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
}//if
}//for
}//if me != num_processes
else{
int start = me * chunk;
int end = 50000 - start;
for(i = start; i < end; i++){
int minedits = levenshtein(word1, strlen(word1), dict[i], strlen(dict[i]));
int thresholdPercentage = (100 * minedits) / max(strlen(word1), strlen(dict[i]));
if(thresholdPercentage < threshold){
int number_to_send = i;
MPI_Send(&number_to_send, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
}
}
}//me == num_processes
}//BIG else
return;
}//COMPUTE OUTPUT
void set_data(){
prompt();
MPI_Bcast(&enterWord,20 ,MPI_CHAR, 0, MPI_COMM_WORLD);
}//p0_send_inpui
//--------------------------MAIN-----------------------------//
main(int argc, char **argv){
int ierr, num_procs, my_id, loop;
FILE *myFile;
loop = 0;
for(i=0;i<50000;i++){
suggestions[i] = calloc(SIZE, sizeof(char));
}
ierr = MPI_Init(NULL, NULL);
ierr = MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
ierr = MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
printf("Check in from %d of %d processors\n", my_id, num_procs);
set_data();
myWord = enterWord;
myFile = fopen("words", "r");
if(myFile != NULL){
for(i=0;i<50000;i++){
dict[i] = calloc(SIZE, sizeof(char));
fscanf(myFile, "%s", dict[i]);
}//for
fclose(myFile);
}//read word list into dictionary
else printf("File not found");
if(my_id == 0){
words_added = p0_compute_output(num_procs, enterWord);
printf("words added so far: %d\n", words_added);
p0_receive_output(words_added);
printf("Threshold: %d\nWords To print: %d\n%s\n", threshold, wordsToPrint, myWord);
ierr = MPI_Finalize();
}
else{
printf("my word %s*\n", enterWord);
compute_output(num_procs, my_id, enterWord);
// printf("Process %d terminating...\n", my_id);
ierr = MPI_Finalize();
}
for(i=0;i<wordsToPrint;i++){
printf("*%s\n", suggestions[i]);
}//print suggestions
return (0);
}//END MAIN
Here are a few problems I see with what you're doing:
prompt() should only be called by rank 0.
The dictionary file should be read only by rank 0, then broadcast the array out to the other ranks
Alternatively, have rank 1 read the file while rank 0 is waiting for input, broadcast input and dictionary afterwards.
You're making the compute_output step overly complex. You can merge p0_compute_output and compute_output into one routine.
Store an array of indices into dict in each rank
This array will not be the same size in every rank, so the simplest way to do this would be to send from each rank a single integer indicating the size of the array, then send the array with this size. (The receiving rank must know how much data to expect). You could also use the sizes for MPI_Gatherv, but I expect this is more than you're wanting to do right now.
Once you have a single array of indices in rank 0, then use this to fill suggestions.
Save the MPI_Finalize call until immediately before the return call
For the final printf call, only rank 0 should be printing that. I suspect this is causing a large part of the "incorrect" result. As you have it, all ranks are printing suggestions, but it is only filled in rank 0. So the others will all be printing blank entries.
Try some of these changes, especially the last one, and see if that helps.

How can be initialize vector array when 2D array vector is full?

I made dynamic vector class..
But the problem show when main function is looping on and on,
my2dArr's row size is increasing when the function is looping
When data is coming on looping, i want to copy new data..
void main()
{
int data[450];
DynamicArray<int> my2dArr(36, 100);
for(int i = 0;i < 36;++i)
{
for(int j = 1;j < 16;++j)
{
my2dArr[i][j-1] = data[i];
}
}
}
// vector class
class DynamicArray
{
public:
DynamicArray(){};
DynamicArray(int rows, int cols): dArray(rows, vector<T>(cols)){}
vector<T> & operator[](int i)
{
return dArray[i];
}
const vector<T> & operator[] (int i) const
{
return dArray[i];
}
void resize(int rows, int cols)//resize the two dimentional array .
{
dArray.resize(rows);
for(int i = 0;i < rows;++i) dArray[i].resize(cols);
}
void clearCOL()
{
for(int i = 0;i < dArray.size();i++)
{
for(int j = 0;j < dArray[i].size();++j)
{
dArray[j].erase();
}
}
}
private:
vector<vector<T> > dArray;
};
The nested for loop should be fine at Initializing your array, but you'd need to put values into the data array to use it in initializing.
If you're only initializing the data once you might consider a third constructor overload that takes in an int[], like so:
DynamicArray( int rows, int cols, T array[] ): dArray( rows, vector< T >( cols ) )
{
for( int i = 0; i < rows; i++ )
{
for( int j = 0; j < cols; j++ )
{
dArray[i][j] = array[i * rows + j];
}
}
}
You'd need to make sure the array was the size you specified. In your example you pass a 450 int array in to initialize a 3,600 int DynamicArray. In you're example you're actually reading illegal data cause you go to the 16th column of each of the 36 rows so you're actually reading 576 elements from a 450 int array. I suppose the array is uninitialized anyway though, so it's all garbage.

Categories

Resources