सी ++ के साथ pthreads
यह मेरी मशीन पर सिर्फ 1 मिनट के भीतर n = 14 हो जाता है। लेकिन चूंकि यह सिर्फ 2-कोर वाला लैपटॉप है, इसलिए मुझे उम्मीद है कि 8-कोर टेस्ट मशीन 2 मिनट के अंदर n = 15 खत्म कर सकती है। मेरी मशीन पर लगभग 4:20 मिनट लगते हैं।
मैं वास्तव में कुछ अधिक कुशल के साथ आने की उम्मीद कर रहा था। वहाँ गया है मिल गया और अधिक कुशलता से एक द्विआधारी मैट्रिक्स की नियत गणना करने के लिए एक तरह से किया जाना है। मैं कुछ प्रकार के गतिशील प्रोग्रामिंग दृष्टिकोण के साथ आना चाहता था जो निर्धारक गणना में +1 और -1 शब्दों को गिनता है। लेकिन यह अभी तक एक साथ नहीं आया है।
चूँकि बाउंटी समाप्त होने वाली है, इसलिए मैंने मानक ब्रूट फ़ोर्स अप्रोच लागू किया:
- सभी संभव टोलपिट्ज़ मैट्रिस पर लूप करें।
- प्रत्येक ट्रांसपोज़्ड मैट्रिक्स जोड़ी में दो में से एक को छोड़ दें। चूंकि मैट्रिक्स को बिटमास्क मानों द्वारा वर्णित किया गया है, इसलिए यह उन सभी मूल्यों को छोड़ कर करना आसान है, जहां बिटकॉम्स का उलटा बिटमैप के मुकाबले छोटा होता है।
- दृढ़ संकल्प की गणना एक पाठ्य पुस्तक एलआर अपघटन के साथ की जाती है। कुछ मामूली प्रदर्शन ट्यूनिंग को छोड़कर, मैंने अपने कॉलेज के संख्यात्मक तरीकों की किताब से एल्गोरिथ्म में मुख्य सुधार किया है कि मैं एक सरल धुरी रणनीति का उपयोग करता हूं।
- समांतरकरण 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;
}