c ++ связанный список пропущенных узлов после размещения в нескольких потоках в x64 linux; Зачем?

Я включил исходный код, который вы можете скомпилировать и увидеть проблему для себя. скомпилировать с помощью g ++ -lpthread list-memchk.cpp -o list-memchk

Выполните это, например, ./list-memchk 43000000 30000000 10

я включил три файла, первый,

Список-memchk.cpp

#include <cstdlib>
#include <iostream>
#include <pthread.h>using namespace std;struct node
{
public :
unsigned int part1; // 4 bytes
unsigned int part2; // 4 bytes
node *next;         //pointer, 8 bytes on 64 bit system
unsigned int read_part1();
};struct LinkedList
{
public:
LinkedList();
void insert(unsigned int data[], unsigned int data1);
bool isEmpty() const;
node* head;
};

unsigned int node::read_part1() {
return part1;
}
LinkedList::LinkedList():
head(NULL)
{
}

bool LinkedList::isEmpty() const
{
return (head == NULL);
}

void LinkedList::insert(unsigned int data[], unsigned int data1)
{node* oldHead = head;
node* newHead = new node();
newHead->part1 = data[0];
newHead->part2 = data1;
newHead->next = oldHead;
head = newHead;

}

unsigned int allocations = 300000000;
unsigned int index_size = 430000000;//index of lists, 430m,.
pthread_mutex_t mutex;
//will be creatad on heap
LinkedList *list = NULL;unsigned long node_count() {

unsigned long numNodes = 0;for (int i=0; i<index_size; i++)
{node* current = list[i].head;

// if root is null, the number of nodes is 0
if(current != NULL) {

// if root is not null, we have at least one node
numNodes++;

// count all nodes
while(current->next != NULL) {
numNodes++;
current = current->next;
}

}

}

return numNodes;

}#include "alloc_threads.cpp"void start_threads(int thread_count) {

alloc_threads alloc_thr[thread_count];//thread objects
pthread_t threads[thread_count];

pthread_mutex_init(&mutex, NULL);

for (int i=0; i<thread_count; i++)
{

alloc_threads *rr;

rr = new alloc_threads(list, mutex, allocations);
alloc_thr[i] = *rr;

pthread_create(&threads[i], NULL, &alloc_threads::allocation_helper,&alloc_thr[i]);

delete rr;
}

for (int i=0; i<thread_count; i++)
pthread_join( threads[i], NULL);}int main(int argc, char *argv[])

{
if ( argc < 4 )
{
std::cout << "Missing paramaters. " << endl;
std::cout << "Please run me like this : <list-memchk> <index_size> <allocations_per_thread> <thread_count>" << endl;
return 1;
}index_size = strtoul(argv[1], 0, 10);
allocations = strtoul(argv[2], 0, 10);
unsigned int thr_cnt = strtoul(argv[3], 0, 10);

LinkedList list_instance;

cout << "1 LinkedList instance takes [" << sizeof(list_instance) << "] bytes in memory!"<< endl;

node node_instance;

cout << "1 node instance takes [" << sizeof(node_instance) <<"] bytes in memory !"<< endl;list = new (nothrow) LinkedList[index_size];
if (!list)
{
cout << "Error allocating memory" << endl;
return 1;
}unsigned int some_data[] = {00, 01};
unsigned int index;
cout << "Allocating ..." << endl;
start_threads(thr_cnt);unsigned long sk = ((allocations * sizeof(node_instance) + index_size*sizeof(list_instance))) / (1024*1024*1024);

cout << "This process *should* consume around " << sk <<" GBytes of memory, but does it ?"<< endl;

cout << "Allocating done, *check the process size* ..." << endl;cout << "Lets count `nodes` to see how many do we have; counting, please wait ..." << endl;

cout << "We have reached [" << node_count() << "] nodes, expected [" << allocations * thr_cnt << "] nodes. You may press any number key to exit." << endl;

string s;
getline(std::cin, s);return 0;
}

затем,
alloc_threads.cpp

#include "alloc_threads.h"using namespace std;

alloc_threads::alloc_threads()
{
}

void *alloc_threads::allocation_helper(void *context)
{
return ((alloc_threads *)context)->allocation();
}

alloc_threads::alloc_threads(LinkedList* x_list, pthread_mutex_t x_mutex, unsigned int x_allocations){
list = x_list;
mutex = x_mutex;
allocations = x_allocations;
}

void * alloc_threads::allocation(void)
{

cout << "Thread started" << endl;
unsigned int some_data[] = {00, 01};
unsigned int index;
unsigned short inde;

LinkedList *list_instance2 = NULL;
for (int i=0; i<allocations; i++)
{

pthread_mutex_lock(&mutex);index = rand();
inde = (unsigned short)index;
list_instance2 = &list[inde];

list_instance2->insert(some_data, some_data[1]);

pthread_mutex_unlock(&mutex);
}
cout << "Thread finished" << endl;
return 0;
}

alloc_threads::~alloc_threads()
{
}

и наконец,
alloc_threads.h

class alloc_threads{
public:
void *allocation(void);
static void *allocation_helper(void *context);
alloc_threads();
alloc_threads(LinkedList *x_list, pthread_mutex_t x_mutex, unsigned int x_allocations);
~alloc_threads();
private:
pthread_mutex_t mutex;
LinkedList* list;
unsigned int allocations;

};

Сам код вообще не комментируется, но, надеюсь, его не так сложно понять. Что я сделал, так это выделение памяти стандартным распределителем в нескольких параллельных потоках, скажем, 10, например. после того, как распределение сделано во всех потоках, я получаю доступ к каждому узлу и увеличиваю numNodes после успешного доступа. что я обычно получаю, это numNodes значение будет на несколько / несколько сотен или несколько тысяч меньше ожидаемого. что случилось ? и я сделал это с двумя разными распределителями, оба они имеют одинаковое поведение.

0

Решение

Кажется, я неправильно использую мьютекс — он не останавливает одновременную запись потоков в одну и ту же память.

solution я нашел, это: определение переменной мьютекса в list-memchk.cpp и избегать передачи его в потоки, но используя его as is,

list-memchk.cpp:
заменить определение мьютекса этим,

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;

Удалить

pthread_mutex_init(&mutex, NULL);

alloc_threads.h:
удалить мьютекс из этого файла;

alloc_threads.cpp:
Удалить mutex = x_mutex;

Это оно. Нет больше отсутствующих узлов. Тем не менее, скорость выделения жалкая. Похоже, потоки ждут друг друга, чтобы разблокировать мьютекс; Ядра процессора работают на холостом ходу, а распределение занимает огромное количество времени.

0

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

Других решений пока нет …

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