Hello together,
I have a question for you. Since a few weeks I am trying to programm
a small bruteforce application in C on Ubuntu 14.04.1 using Code::Blocks
with gcc-4.8.2. My programm is nothing special. It's just for practise,
Without hashing or something like that. For me the focus is on parallelize
the procedure that generates words. I'm using OpenMP for this small project.
Until now it works good for me. There is just one thing that I would like to
implement, but without success so far.
I want that my programm counts all the generated words, regardless of wether
the search string was found or not. I hope you understand what I'm talking
about. I'm sorry for my bad english. I am from germany.
I declared a global unsigned integer variable with the name 'Counter' for counting all
the generated words.
Because the whole procedure is parallelized, the variable is specified as reduction
variable.
#pragma omp parallel default... reduction ( +: Counter )
So the problem is, that the reduction is not completed until the end of the parallel region,
when the search string was found.
That means only when my programm doesn't have a match, at the end the number of counts for
all generated words is correct. Why? Because when nothing was found, the application reaches
the end of the parallel region and the reduction is completed.
But if my programm has a match, the number of counts is always wrong at the output.
Now, I would like to know, if there is way to exit sane and portable from a parallel region,
without have to wait until all possibilites of words has been tried? Do you understand
what I mean? I.e. we are searching the following string: "4788". I tell my programm the max.
length of words should be 4. From "0" until "9999" altogether are 11110 tries, using just
digits (0123456789) for the brute force procedure. If the word is found, the number of tries (counts)
is 5899.
Is it possible to exit sane and portable from a parallel region earlier?
I.e. when the search string was found? By the same behavior like if nothing was found? So that at the end
the number of counts will displayed correct, even if the word was found?
I have tried something with two variables 'CheckStatus' and 'MyCheckStatus'. This variables should indicate
when work is done (i.e. if there's a match).
With omp atomic read and omp atomic write. But unfortunately without success.
Here is my source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
/* Global variables */
const char Literals[] = "0123456789";
const unsigned int NLiterals = sizeof( Literals ) - 1;
const char TestString[] = "4788";
char EndString[16];
int CheckStatus = 0;
/* Functions */
static void BruteForcer( const int *, const int *, int, unsigned * );
int main()
{
unsigned Counter = 0;
#pragma omp parallel default( none ) shared( CheckStatus ) reduction( +:Counter )
{
for( int WordLength = 0; WordLength < 5; ++WordLength )
{
int FirstEntry[WordLength], LastEntry[WordLength], MyCheckStatus;
for( int j = 0; j < WordLength; ++j )
FirstEntry[j] = LastEntry[j] = 0;
#pragma omp for schedule( dynamic )
for( int i = 0; i < NLiterals; ++i )
{
FirstEntry[0] = i;
LastEntry[0] = i + 1;
#pragma omp atomic read
MyCheckStatus = CheckStatus;
if( !MyCheckStatus )
BruteForcer( FirstEntry, LastEntry, WordLength, &Counter );
}
}
}
if( CheckStatus )
fprintf( stdout, "\nWord found: '%s'! %u tries.\n", EndString, Counter );
else
fprintf( stdout, "\nNothing found: '%s'! %u tries.\n", "Empty", Counter );
exit( EXIT_SUCCESS );
}
static void BruteForcer( const int *FstEntry, const int *LstEntry, int WdLength, unsigned *CounterPtr )
{
char Word[WdLength];
int Entry[WdLength + 1];
int i, j;
memset( Entry, '\0', WdLength );
/* copy FstEntry to Entry */
for( i = 0; i < WdLength; ++i )
Entry = FstEntry;
i = 0;
while( i < WdLength )
{
/* generate word */
for( i = 0; i < WdLength; ++i )
Word = Literals[Entry];
/* null-byte at end of string */
Word[WdLength] = '\0';
++*CounterPtr;
/* string compare */
if( strncmp( TestString, Word, sizeof( TestString ) ) == 0 )
{
strncpy( EndString, Word, strlen( Word ) );
#pragma omp atomic write
CheckStatus = 1;
return;
}
/* increment Entry */
for( i = 0; i < WdLength && ++Entry[WdLength-i-1] == NLiterals; i++ )
Entry[WdLength-i-1] = 0;
/* when Entry != LstEntry then leave loop */
for( j = 0; j < WdLength; ++j )
if( Entry[j] != LstEntry[j] )
break;
/* when Entry == LstEntry leave function */
if( j == WdLength )
return;
}
}
Without parallelization I have this output:
Word found: '4788' ! 5899 tries!
That is correct. But with parallelization the output is as follows:
Word found: '4788' ! 10899 tries! (Each time the number is another!)
The goal is, that the number of counts is always correct with parallelization.
Please could you help me with this issue? If possible with small code examples or improving my source code, too. I would be very very appreciated.
DaveX