সি ++ পাইথ্রেড সহ
আমার মেশিনে 1 মিনিটের নিচে এটি n = 14 এ যায়। তবে যেহেতু এটি কেবলমাত্র একটি 2-কোর ল্যাপটপ, আমি আশা করি 8-কোর টেস্ট মেশিনটি 2 মিনিটের মধ্যে n = 15 শেষ করতে পারে। এটি আমার মেশিনে প্রায় 4:20 মিনিট সময় নেয়।
আমি সত্যিই আরও দক্ষ কিছু নিয়ে আসার আশা করছিলাম। সেখানে আছে পেয়েছিলাম আরো দক্ষতার সঙ্গে একটি বাইনারি ম্যাট্রিক্স নির্ধারিত নিরূপণ করা একটি উপায় হতে হবে। আমি এমন কিছু গতিশীল প্রোগ্রামিং পদ্ধতির সাথে আসতে চেয়েছিলাম যা নির্ধারক গণনায় +1 এবং -1 পদগুলিকে গণনা করে। তবে এটি এখনও পর্যন্ত একসাথে আসে নি।
যেহেতু অনুগ্রহের মেয়াদ শেষ হতে চলেছে, তাই আমি স্ট্যান্ডার্ড ব্রুট ফোর্স পদ্ধতির প্রয়োগ করেছি:
- সমস্ত সম্ভাব্য টোপলিটজ ম্যাট্রিক্সের উপর লুপ করুন।
- প্রতি পরিবহিত ম্যাট্রিক্স জুটিতে দু'এর একটিতে যান ip যেহেতু ম্যাট্রিক্স বিটমাস্ক মান দ্বারা বর্ণিত, তাই বিটমাস্কের বিপরীত বিটমাস্কের চেয়ে ছোট যেখানে সমস্ত মানগুলি এড়িয়ে যাওয়া সহজ।
- নির্ধারণটি একটি পাঠ্য বইয়ের সাথে গণনা করা হয় LR পচন। কিছু অল্প পারফরম্যান্স টিউনিং বাদে, আমার কলেজের সংখ্যা সংক্রান্ত পদ্ধতি বই থেকে অ্যালগরিদমে আমি যে প্রধান উন্নতি করেছি তা হ'ল আমি একটি সহজ পাইভট কৌশল ব্যবহার করি।
- সমান্তরালকরণ pthreads দিয়ে করা হয়। প্রতিটি থ্রেড দ্বারা প্রক্রিয়াকৃত মানগুলির জন্য কেবল নিয়মিত ব্যবধান ব্যবহার করায় খুব খারাপ লোড ভারসাম্য হয়, তাই আমি কিছু সুইজলিংয়ের প্রবর্তন করি।
আমি এটি ম্যাক ওএসে পরীক্ষা করেছি, তবে আমি আগে উবুন্টুতে অনুরূপ কোড ব্যবহার করেছি, তাই আমি আশা করি এটি কোনও সঙ্কোচ ছাড়াই সংকলন ও চলবে:
- কোনও
.cpp
এক্সটেনশন সহ কোনও ফাইলের মধ্যে কোডটি সংরক্ষণ করুন optim.cpp
।
- সংকলন
gcc -Ofast optim.cpp -lpthread -lstdc++
।
- সাথে চালাও
time ./a.out 14 8
। প্রথম যুক্তিটি সর্বাধিক n
। 14 অবশ্যই 2 মিনিটের নিচে শেষ করা উচিত, তবে আপনি 15 টি চেষ্টা করতে পারলে দুর্দান্ত হবে। দ্বিতীয় যুক্তিটি থ্রেডের সংখ্যা। মেশিনের কররের সংখ্যার মতো একই মান ব্যবহার করা সাধারণত একটি ভাল শুরু, তবে কিছু পরিবর্তনের চেষ্টা করা সময়কে সম্ভবত উন্নত করতে পারে।
কোড তৈরি করতে বা চালাতে আপনার কোনও সমস্যা আছে কিনা তা আমাকে জানান।
#include <stdint.h>
#include <pthread.h>
#include <cstdlib>
#include <iostream>
static int NMax = 14;
static int ThreadCount = 4;
static pthread_mutex_t ThreadMutex;
static pthread_cond_t ThreadCond;
static int BarrierCount = 0;
static float* MaxDetA;
static uint32_t* MaxDescrA;
static inline float absVal(float val)
{
return val < 0.0f ? -val : val;
}
static uint32_t reverse(int n, uint32_t descr)
{
uint32_t descrRev = 0;
for (int iBit = 0; iBit < 2 * n - 1; ++iBit)
{
descrRev <<= 1;
descrRev |= descr & 1;
descr >>= 1;
}
return descrRev;
}
static void buildMat(int n, float mat[], uint32_t descr)
{
int iDiag;
for (iDiag = 1 - n; iDiag < 0; ++iDiag)
{
float val = static_cast<float>(descr & 1);
descr >>= 1;
for (int iRow = 0; iRow < n + iDiag; ++iRow)
{
mat[iRow * (n + 1) - iDiag] = val;
}
}
for ( ; iDiag < n; ++iDiag)
{
float val = static_cast<float>(descr & 1);
descr >>= 1;
for (int iCol = 0; iCol < n - iDiag; ++iCol)
{
mat[iCol * (n + 1) + iDiag * n] = val;
}
}
}
static float determinant(int n, float mat[])
{
float det = 1.0f;
for (int k = 0; k < n - 1; ++k)
{
float maxVal = 0.0f;
int pk = 0;
for (int i = k; i < n; ++i)
{
float q = absVal(mat[i * n + k]);
if (q > maxVal)
{
maxVal = q;
pk = i;
}
}
if (pk != k)
{
det = -det;
for (int j = 0; j < n; ++j)
{
float t = mat[k * n + j];
mat[k * n + j] = mat[pk * n + j];
mat[pk * n + j] = t;
}
}
float s = mat[k * n + k];
det *= s;
s = 1.0f / s;
for (int i = k + 1; i < n; ++i)
{
mat[i * n + k] *= s;
for (int j = k + 1; j < n; ++j)
{
mat[i * n + j] -= mat[i * n + k] * mat[k * n + j];
}
}
}
det *= mat[n * n - 1];
return det;
}
static void threadBarrier()
{
pthread_mutex_lock(&ThreadMutex);
++BarrierCount;
if (BarrierCount <= ThreadCount)
{
pthread_cond_wait(&ThreadCond, &ThreadMutex);
}
else
{
pthread_cond_broadcast(&ThreadCond);
BarrierCount = 0;
}
pthread_mutex_unlock(&ThreadMutex);
}
static void* threadFunc(void* pData)
{
int* pThreadIdx = static_cast<int*>(pData);
int threadIdx = *pThreadIdx;
float* mat = new float[NMax * NMax];
for (int n = 1; n <= NMax; ++n)
{
uint32_t descrRange(1u << (2 * n - 1));
float maxDet = 0.0f;
uint32_t maxDescr = 0;
uint32_t descrInc = threadIdx;
for (uint32_t descrBase = 0;
descrBase + descrInc < descrRange;
descrBase += ThreadCount)
{
uint32_t descr = descrBase + descrInc;
descrInc = (descrInc + 1) % ThreadCount;
if (reverse(n, descr) > descr)
{
continue;
}
buildMat(n, mat, descr);
float det = determinant(n, mat);
if (det > maxDet)
{
maxDet = det;
maxDescr = descr;
}
}
MaxDetA[threadIdx] = maxDet;
MaxDescrA[threadIdx] = maxDescr;
threadBarrier();
// Let main thread output results.
threadBarrier();
}
delete[] mat;
return 0;
}
static void printMat(int n, float mat[])
{
for (int iRow = 0; iRow < n; ++iRow)
{
for (int iCol = 0; iCol < n; ++iCol)
{
std::cout << " " << mat[iRow * n + iCol];
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main(int argc, char* argv[])
{
if (argc > 1)
{
NMax = atoi(argv[1]);
if (NMax > 16)
{
NMax = 16;
}
}
if (argc > 2)
{
ThreadCount = atoi(argv[2]);
}
MaxDetA = new float[ThreadCount];
MaxDescrA = new uint32_t[ThreadCount];
pthread_mutex_init(&ThreadMutex, 0);
pthread_cond_init(&ThreadCond, 0);
int* threadIdxA = new int[ThreadCount];
pthread_t* threadA = new pthread_t[ThreadCount];
for (int iThread = 0; iThread < ThreadCount; ++iThread)
{
threadIdxA[iThread] = iThread;
pthread_create(threadA + iThread, 0, threadFunc, threadIdxA + iThread);
}
float* mat = new float[NMax * NMax];
for (int n = 1; n <= NMax; ++n)
{
threadBarrier();
float maxDet = 0.0f;
uint32_t maxDescr = 0;
for (int iThread = 0; iThread < ThreadCount; ++iThread)
{
if (MaxDetA[iThread] > maxDet)
{
maxDet = MaxDetA[iThread];
maxDescr = MaxDescrA[iThread];
}
}
std::cout << "n = " << n << " det = " << maxDet << std::endl;
buildMat(n, mat, maxDescr);
printMat(n, mat);
threadBarrier();
}
delete[] mat;
delete[] MaxDetA;
delete[] MaxDescrA;
delete[] threadIdxA;
delete[] threadA;
return 0;
}