使用pThreads创建和管理单独的堆

时间:2014-03-27 22:41:04

标签: c++ multithreading pthreads heap posix

在这种情况下,我有一个无符号整数向量的向量,我正在处理。在正常情况下,将有256个向量的1048576个无符号整数。我想使用pThread c ++ API,这样每个pthread将在其指定的无符号整数子列表(长度为1048576)上进行以下工作。

for(int i = 0; i < list_size; i++)
{
    int *arg = (int *) malloc(sizeof(*arg));
    *arg = i;
    thread_err = pthread_create(&(threads[i]), NULL, &Heap_Build, arg);
    if (thread_err != 0)
        printf("\nCan't create thread :[%s]", strerror(thread_err));
}

从上面的代码中可以看出,我只是生成与主列表中的子列表一样多的线程,并且我将每个都带有索引值的子列表发送到子列表的主向量中,以便他们知道他们正在有效处理哪个子列表。

void* Heap_Build(void *arg)
{
   int main_list_index = *((int *)arg);

   //pthread_mutex_lock( &mutex1 );
   num_of_nodes = 0;
   pheapType heap = pheapType(malloc((k+usage_offset) * sizeof(heapType)));
   unsigned int sublist_value;

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

     sublist_value = main_list.at(main_list_index).at(i);

     Heap_Insert_Node(heap, sublist_value); 
   }


   for(int i = k; i < sub_list_size; i++)
   {
       sublist_value = main_list.at(main_list_index).at(i);


       if(sublist_value < heap[usage_offset])
       {
          Heap_Update_Key_CPU(heap, 0, sublist_value);
       }
    }
    //pthread_mutex_unlock( &mutex1 );
    cpu_results[main_list_index] = heap[usage_offset];
    free(heap);
}

请注意

  • num_of_nodes - 当前插入堆结构的节点数。在每个堆构造之前将其设置为0,并由update_key和insert_node操作用于确定堆数组中用于放置值的索引。

  • sublist_value - 正在处理子列表的当前值。

上面的函数实际上分配了一个内存数组来构建一个来自第一个&#39; k&#39;线程正在处理的子列表中的元素。然后,它使用堆的更新密钥操作处理剩余的元素。

因此,每个线程都被赋予一个索引,该索引指向无符号整数子列表的全局向量中的子列表。它从子列表中的第一个第k个元素创建一个堆,然后根据它创建的堆处理子列表中剩余的第k个元素。

如果我做2 ^ 8个大小为2 ^ 8的子列表或256个处理256个256个整数的子列表甚至1个2 ^ 20个整数的子列表,我可以让一切正常工作,但在测试用例,2 ^ 8个2 ^ 8个整数的子列表。该程序要么有分段错误,要么只是中止。

如果我取消注释互斥锁。任何情况下工作正常,但不幸的是,它将以串行方式进行计算。我不确定这个问题是什么,主要是因为我在处理POSIX线程方面很陌生。显然,问题必须处理子列表中的整数数量太多以及线程数量和可能的竞争条件,但我不确定如何识别整体计算中的关键区域而不是只是在整个计算中放置一个互斥锁并删除所有并行性。

如果需要,我可以提供Heap_Build中使用的两个堆函数的代码,但我并没有试图用太多的代码来解决这个问题。

编辑:我认为上面代码中的问题是所有线程都引用相同的内存空间,而不是每个线程分配自己的堆结构。因此,当完成计算的第一个线程释放为堆&#39;分配的内存空间时,其他线程正在引用无效的内存区域,从而导致分段错误。 如果我删除了免费(堆)&#39;行,错误消失但值不正确。我不确定如何纠正这个问题,我认为这需要给每个pthread它自己的堆内存空间来工作,这样任何一个线程都不会踩到彼此的数据,但我不太清楚如何做到这一点。

1 个答案:

答案 0 :(得分:0)

在您显示的代码中,每个运行Heap_Build函数的线程都会分配自己的堆结构来处理:

pheapType heap = pheapType(malloc((k+usage_offset) * sizeof(heapType)));

这个内存是一个线程的本地内存(在某种意义上它是其他线程不知道的,除非在问题中没有显示的某些代码共享),因此我认为你的粗体问题是无效的。

但是,您的代码不会检查内存是否已真正分配。 256个1048576整数的向量已经消耗了2 ^(20 + 8 + 2)= 2 ^ 30或1GB的内存。如果代码是32位且分配大小很大,则可能发生没有足够长度的空闲内存块。然后,在某些线程中heap可以为NULL,并且使用这样的“堆”进行操作可能会导致崩溃。

另一种可能性是Heap_Insert_Node和/或Heap_Update_Key_CPU中的数据争用,以防这些函数产生副作用(例如修改一些全局变量)。