OpenMPを使用してコンピューティングを並列化する

MD5ハッシュからパスワードを回復するというタスクがあります。 パスワードは単純で、7桁で構成され、8桁で始まります。 私はすぐに予約をします-私のパスワード、私はそれを陳腐に忘れました、そしてこれは他人のパスワードを総当たり攻撃する方法についての指示ではありません。

プログラムは、可能な限り迅速に結果を得るために、いくつかのスレッドで動作する必要があります。 デュアルコアプロセッサを搭載したコンピューターで実行するためだけに。 1つのスレッドで両方のコアを最大化することはできません。

2つの方法を検討してください:複数のワークフローを作成する、およびOpenMPを使用する


最初の方法は、複数のスレッドを作成することです。



簡単にするために、結果を出力するときにフローを同期せずに、問題を正面から解決します。 それ以外の場合は、デッドロック、またはむしろそれらの不在に注意する必要があります。
//
const int g_nNumberOfThreads = 4;

const int g_nFrom = 8000000;
const int g_nTo = 8999999;
const string g_strCompareWith = "4ac7b1796b90478f2991bb9a7b05d2bf" ;

time_t g_timeElapsed;

// ,
struct THREAD_PARAMS
{
int nFrom;
int nTo;
};

// MD5
BOOL GetMD5Hash( string strIn, string &strHash)

//
DWORD WINAPI _WorkerThread(LPVOID pParams)
{
//
THREAD_PARAMS *pThreadParams = (THREAD_PARAMS*)pParams;

int nFrom = pThreadParams->nFrom;
int nTo = pThreadParams->nTo;

delete pParams;

string strHash;

for ( int i = nFrom; i < nTo; ++i)
{
stringstream stream;
stream << i;

//
GetMD5Hash(stream.str(), strHash);

//
if (strHash == g_strCompareWith)
{
//
cout << "Password is: " << stream.str() << endl;
cout << "Elapsed time: " << time(NULL) - g_timeElapsed << " sec." << endl;
exit(0);
}

// 10000
if ((i % 10000) == 0)
{
cout << "Current password: " << i << " Elapsed time: " << time(NULL) - g_timeElapsed << " sec." << endl;
}
}

return 0;
}

//
void MultiThreadWay()
{
int nDataLength = ( int )(g_nTo - g_nFrom) / g_nNumberOfThreads;
HANDLE *hThreads = new HANDLE[g_nNumberOfThreads];

for ( int i = 0; i < g_nNumberOfThreads; ++i)
{
THREAD_PARAMS *pParams = new THREAD_PARAMS();

pParams->nFrom = g_nFrom + (i * nDataLength);
pParams->nTo = pParams->nFrom + nDataLength;

hThreads[i] = CreateThread(NULL, 0, _WorkerThread, pParams, 0, NULL);

Sleep(100);
}

WaitForMultipleObjects(g_nNumberOfThreads, hThreads, TRUE, INFINITE);

delete [] hThreads;
}

//
int _tmain( int argc, _TCHAR* argv[])
{
g_timeElapsed = time(NULL);

MultiThreadWay();

return 0;
}


*このソースコードは、 ソースコードハイライターで強調表示されました。


方法2-OpenMPを使用する



ヘッダーファイルを含める必要があります

#include <omp.h>

/ openmpコンパイラオプションを追加します。 Visual Studioでは、これはプロジェクトプロパティを介して行われます。



//
const int g_nNumberOfThreads = 4;

const int g_nFrom = 8000000;
const int g_nTo = 8999999;
const string g_strCompareWith = "4ac7b1796b90478f2991bb9a7b05d2bf" ;

time_t g_timeElapsed;

// MD5
BOOL GetMD5Hash( string strIn, string &strHash)

int _tmain( int argc, _TCHAR* argv[])
{
g_timeElapsed = time(NULL);

//
omp_set_num_threads(g_nNumberOfThreads);

// , .
// g_nNumberOfThreads .
// .
#pragma omp parallel for
for ( int i = g_nFrom; i < g_nTo; ++i)
{
//
//
string strHash;
stringstream stream;

stream << i;

//
GetMD5Hash(stream.str(), strHash);

//
if (strHash == g_strCompareWith)
{
cout << "Password is: " << stream.str() << endl;
cout << "Elapsed time: " << time(NULL) - g_timeElapsed << " sec." << endl;
exit(0);
}

// 10000
if ((i % 10000) == 0)
{
// .
// , ""
#pragma omp critical
{
cout << "Current password: " << i << " Elapsed time: " << time(NULL) - g_timeElapsed << " sec." << endl;
}
}
}

return 0;
}


*このソースコードは、 ソースコードハイライターで強調表示されました。


OpenMPを使用すると、コードははるかに短くなります。 この場合、私のコンピューターでの2番目の方法によるパスワードの計算ははるかに高速でした。 両方の方法が両方のコアをほぼ完全に「ロード」したという事実にもかかわらず。

OpenMPに興味がある場合は、IntelのWebサイトに投稿された記事を参照してください。

OpenMPの使用開始
OpenMPを使用したスレッド間の効率的な負荷分散
高度なOpenMPプログラミング

また、 OpenMP Webサイトにアクセスすることを忘れないでください。 そこで、OpenMPおよびOpenMP仕様をサポートするコンパイラのリストを見つけることができます。

Source: https://habr.com/ru/post/J71296/


All Articles