C++ 在pthread中使用堆分配>;100MB内存

C++ 在pthread中使用堆分配>;100MB内存,c++,memory,pthreads,heap,ram,C++,Memory,Pthreads,Heap,Ram,一个简单的pthread测试用例根据top的VIRT列来分配以下RAM: 无pthread/堆使用:4224 kB 使用pthread但不使用堆:14716 kB 在main(但不是线程)中使用pthread和heap:23632kb 在主线程和线程中使用pthread和heap:89168 kB 为什么要分配这么多RAM?valgrind——页面为heap=yes,显示127MB的峰值堆分配 我读到线程共享一个堆,那么为什么在pthread中使用堆时会出现大的跳跃呢?代码稍后将针对资源非常有限

一个简单的pthread测试用例根据top的VIRT列来分配以下RAM:

无pthread/堆使用:4224 kB
使用pthread但不使用堆:14716 kB
在main(但不是线程)中使用pthread和heap:23632kb
在主线程和线程中使用pthread和heap:89168 kB

为什么要分配这么多RAM?valgrind——页面为heap=yes,显示127MB的峰值堆分配

我读到线程共享一个堆,那么为什么在pthread中使用堆时会出现大的跳跃呢?代码稍后将针对资源非常有限的嵌入式系统,因此了解这些分配非常重要

使用以下代码编译(Ubuntu 16.04上的g++版本5.4.0):

thread.cpp:

#include <iostream>
#include <pthread.h>
#include <unistd.h>

#define USE_THREAD
#define USE_HEAP_IN_MAIN
#define USE_HEAP_IN_THREAD

int *arr_thread;
int *arr_main;

void *use_heap(void *arg){
#ifdef USE_HEAP_IN_THREAD
    arr_thread=new int[10];
    arr_thread[0]=1234;
#endif
    usleep(10000000);
}

int main() {
    pthread_t t1;
#ifdef USE_HEAP_IN_MAIN
    arr_main=new int[10];
    arr_main[0]=5678;
#endif

#ifdef USE_THREAD
    pthread_create(&t1, NULL, &use_heap, NULL);
    pthread_join(t1,NULL);
#else
    usleep(10000000);
#endif

    return 0;
}
#包括
#包括
#包括
#定义使用线程
#在\u MAIN中定义使用\u堆\u
#定义在线程中使用堆
内螺纹;
内线*外线干线;
void*使用_堆(void*arg){
#ifdef在线程中使用堆
arr_thread=新整数[10];
arr_线程[0]=1234;
#恩迪夫
美国LEEP(10000000);
}
int main(){
pthread_t t1;
#ifdef使用主目录中的堆
arr_main=新整数[10];
arr_main[0]=5678;
#恩迪夫
#ifdef使用_螺纹
pthread_create(&t1,NULL,&use_heap,NULL);
pthread_join(t1,NULL);
#否则
美国LEEP(10000000);
#恩迪夫
返回0;
}
  • 编辑以使用全局PTR演示-O2的效果
我读到线程共享一堆

那么,为什么在pthread中使用堆时会出现大的跳跃呢

GLIBC(和许多其他)malloc实现使用每线程竞技场来避免所有线程争夺单个堆锁

每个线程中的第一个
malloc(1)
将创建一个全新的竞技场(通常通过
mmap
)。竞技场的大小是一个实现细节,2或4 MB不是不合理的

通过顶部的VIRT柱测量的RAM

这不是一个好的测量。一个程序可以有巨大的virt大小,但实际使用的内存很少。只需尝试mmap 1GB内存,但不要触摸它——您的程序
VIRT
将达到极限,但系统可用内存将不会减少

代码稍后将针对资源非常有限的嵌入式系统,因此了解这些分配非常重要


在这种情况下,您需要比
top
更好的工具。准确计算Linux上的实际内存使用量有些棘手。您可以从查看
/proc/$pid/smap

开始,除非您希望
malloc()
锁定每个分配(速度非常慢),否则您需要
malloc()
实现,其中每个线程都有自己的内存块分配给该线程中的
malloc()
调用(当一个线程中的分配
malloc()
ed在另一个线程中是
free()
d时,您仍然偶尔需要同步)@EOF这很有意义,所以你会说这是预期的行为?+10MB使用堆听起来很合理,但为什么+66MB跳转使用线程中的堆?我按照你的建议查看了进程的smaps文件。有一个65536KB的条目,RSS为零,所以正如你所说,进程没有使用内存。但是,它可以使用-我可以创建一个64MB(-1kB)的数组中的VIRT项没有增加。那么这不意味着64 MB的系统资源分配给了进程吗?同样,这是64 MB,不能分配给其他进程吗?很明显,不同的线程应该分配给不同的Arena,但是为什么pthread实例在主线程只有8 MB的情况下得到64 MB?
#include <iostream>
#include <pthread.h>
#include <unistd.h>

#define USE_THREAD
#define USE_HEAP_IN_MAIN
#define USE_HEAP_IN_THREAD

int *arr_thread;
int *arr_main;

void *use_heap(void *arg){
#ifdef USE_HEAP_IN_THREAD
    arr_thread=new int[10];
    arr_thread[0]=1234;
#endif
    usleep(10000000);
}

int main() {
    pthread_t t1;
#ifdef USE_HEAP_IN_MAIN
    arr_main=new int[10];
    arr_main[0]=5678;
#endif

#ifdef USE_THREAD
    pthread_create(&t1, NULL, &use_heap, NULL);
    pthread_join(t1,NULL);
#else
    usleep(10000000);
#endif

    return 0;
}