使用pThreads创建和管理单独的堆
Creating and managing separate heaps using pThreads
在这种情况下,我有一个正在处理的无符号整数向量的向量。在正常情况下,将有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
中的数据竞争,以防这些函数有副作用(例如修改一些全局变量)。
- 如何在C++中从两个单独的for循环中添加两个数组
- 当vector是tje全局变量时,c++中vector的内存管理
- 用C++在单独的头文件中完成函数体
- 类模板的成员功能的定义在单独的TU中完全专业化
- 如何使用单独文件中的派生类访问友元函数对象
- CoInitialize()在单独的线程上崩溃而不返回
- avrogencpp能为模式中的每种类型生成单独的头文件吗
- 如何维护资源管理器项目视图中当前可见的项目列表
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 资源管理设计模式
- 使用"Task"函数指针队列定义作业管理器
- 转换函数,将 std::数组的双精度作为参数或双精度作为参数单独转换
- 单独定义模板化嵌套类方法的正确语法
- 如何将 2 个类分成单独的 .h 文件并正确设置它们
- C++ 链接到单独的.cpp文件说"multiple definitions"
- 实现动态插件管理器
- Alt+Enter 在 Win32 应用中,管理大小调整和分辨率
- libcurl 和 DNS ttl 中的内部连接管理
- 在一个单独的线程中管理OpenGL上下文
- 使用pThreads创建和管理单独的堆