Эффективный способ передачи сигналов и сохранения открытости?

У меня есть код, который пытается выполнить интенсивную матричную обработку, поэтому я подумал, что будет быстрее, если я буду многопоточным. Тем не менее, я намерен сохранить поток живым, чтобы в будущем его можно было использовать для дальнейшей обработки. Проблема в том, что многопоточная версия кода работает медленнее, чем отдельный поток, и я считаю, что проблема заключается в том, как я сигнализирую / поддерживаю мои потоки живыми.

Я использую pthreads на Windows и C ++. Вот мой код для потока, где RunTest () это функция, в которой выполняются матричные вычисления:

void* playQueue(void* arg)
{
while(true)
{
pthread_mutex_lock(&queueLock);
if(testQueue.empty())
break;
else
testQueue.pop();
pthread_mutex_unlock(&queueLock);
runtest();
}
pthread_exit(NULL);
}

playQueue () Функция — это та, что передана в pthread, и на данный момент у меня есть то, что существует очередь (testQueue), скажем, 1000 элементов и 100 потоков. Каждый поток будет продолжать работать до тех пор, пока очередь не станет пустой (следовательно, содержимое внутри мьютекса).

Я полагаю, что причина, по которой многопоточность запускается так медленно, кроется в так называемом ложном разделении (я думаю?) И в моем методе сигнализации потока для вызова RunTest () и поддержание нити в беде.

Что может быть эффективным способом сделать это, чтобы многопоточная версия работала быстрее (или, по крайней мере, так же быстро), как итеративная версия?

Вот полная версия моего кода (без матрицы)

# include <cstdlib>
# include <iostream>
# include <cmath>
# include <complex>
# include <string>
# include <pthread.h>
# include <queue>

using namespace std;

# include "matrix_exponential.hpp"# include "test_matrix_exponential.hpp"# include "c8lib.hpp"# include "r8lib.hpp"
# define NUM_THREADS 3

int main ( );
int counter;
queue<int> testQueue;
queue<int> anotherQueue;
void *playQueue(void* arg);
void runtest();
void matrix_exponential_test01 ( );
void matrix_exponential_test02 ( );
pthread_mutex_t anotherLock;
pthread_mutex_t queueLock;
pthread_cond_t queue_cv;

int main ()

{
counter = 0;

/* for (int i=0;i<1; i++)
for(int j=0; j<1000; j++)
{
runtest();
cout << counter << endl;
}*/

pthread_t threads[NUM_THREADS];
pthread_mutex_init(&queueLock, NULL);
pthread_mutex_init(&anotherLock, NULL);
pthread_cond_init (&queue_cv, NULL);
for(int z=0; z<1000; z++)
{
testQueue.push(1);
}
for( int i=0; i < NUM_THREADS; i++ )
{
pthread_create(&threads[i], NULL, playQueue, (void*)NULL);
}
while(anotherQueue.size()<NUM_THREADS)
{

}
cout << counter;
pthread_mutex_destroy(&queueLock);
pthread_cond_destroy(&queue_cv);
pthread_cancel(NULL);
cout << counter;
return 0;
}

void* playQueue(void* arg)
{
while(true)
{
cout<<counter<<endl;
pthread_mutex_lock(&queueLock);
if(testQueue.empty()){
pthread_mutex_unlock(&queueLock);
break;
}
else
testQueue.pop();
pthread_mutex_unlock(&queueLock);
runtest();
}
pthread_mutex_lock(&anotherLock);
anotherQueue.push(1);
pthread_mutex_unlock(&anotherLock);
pthread_exit(NULL);
}

void runtest()
{
counter++;
matrix_exponential_test01 ( );
matrix_exponential_test02 ( );
}

Таким образом, здесь «matrix_exponential_tests» взяты из этот сайт с разрешения и где все математике математике происходит. Счетчик используется только для отладки и проверки работоспособности всех экземпляров.

0

Решение

Разве это не застряло?

while(true)
{
pthread_mutex_lock(&queueLock);
if(testQueue.empty())
break; //<----------------you break without unlock the mutex...
else
testQueue.pop();
pthread_mutex_unlock(&queueLock);
runtest();
}

Раздел между блокировкой и разблокировкой работает медленнее, чем если бы он был в одном потоке.

мьютексы замедляют вас. Вы должны заблокировать только критическую секцию, и если вы хотите ускорить ее, постарайтесь вообще не использовать mutex.

Вы можете сделать это, предоставив тест через аргумент функции, а не используя очередь.

Одним из способов избежать использования мьютекса является использование vector без удаления и std::atomic_int (c ++ 11) в качестве индекса (или для блокировки только получения текущего индекса и приращения)

или используйте итератор так:

vector<test> testVector;
vector<test>::iterator it;
//when it initialized to:
it = testVector.begin();

Теперь ваш цикл может быть таким:

while(true)
{
vector<test>::iterator it1;
pthread_mutex_lock(&queueLock);
it1 = (it==testVector.end())? it : it++;
pthread_mutex_unlock(&queueLock);

//now you outside the critical section:
if(it==testVector.end())
break;
//you don't delete or change the vector
//so you can use the it1 iterator freely
runtest();
}
3

Другие решения


По вопросам рекламы [email protected]