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

Creating and managing separate heaps using pThreads

本文关键字:单独 管理 pThreads 创建 使用      更新时间:2023-10-16

在这种情况下,我有一个正在处理的无符号整数向量的向量。在正常情况下,将有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 -正在处理的子列表的当前值。

上面的函数实际上分配了一个内存数组,从线程正在处理的子列表中的前k个元素构建一个堆。然后,它使用堆的更新键操作处理剩余的元素。

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

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

如果我取消互斥锁的注释。任何情况下都可以,但不幸的是,它将以串行方式进行计算。我不确定问题可能是什么,主要是因为我是处理POSIX线程的新手。显然,这个问题必须处理子列表中的整数数量与线程数量和可能的竞争条件相结合,但我不确定如何识别整个计算中的关键区域,而不是仅仅在整个计算中放置互斥锁并删除所有并行性。

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

编辑:我认为上面代码中的问题是所有线程都引用相同的内存空间,'堆',而不是每个线程分配自己的堆结构。因此,当完成计算的第一个线程释放分配给'heap'的内存空间时,其他线程正在引用无效的内存区域,从而出现分段错误。如果我删除'free(heap)'行,错误消失,但值不正确。我不确定如何纠正这一点,我认为这需要给每个pthread它自己的堆内存空间内工作,使没有线程会踩在对方的数据,但我不太确定如何实现这一点。

在您所展示的代码中,每个运行Heap_Build函数的线程分配自己的堆结构来使用:

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

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

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

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