| by msbeta | No comments

C++多线程编程-分析每个函数的内存占用

最近遇到一个“内存占用不断增加”的问题,从代码上没有分析出任何异常,束手无策只有只有借助第三方工具Google Heap Profiler。Google Heap Profiler是Google开源性能内存检测工具GPerfTools系列工具中的一个,可以帮助我们检测代码中出现的内存泄露,帮助我们了解程序中每一行代码占用了多少内存。

1. Google Heap Profiler的安装

安装环境: Ubuntu 18.04

Google GPerfTools工具的Github: https://github.com/gperftools/gperftools

编译安装:[……]

继续阅读

Read More
| by msbeta | No comments

C++多线程编程-设计无锁并发堆栈

今天我们来设计一个并发堆栈(Stack),这个堆栈(Stack)虽然支持多线程访问,但是没有锁。

向堆栈压入数据

在push方法里,使用了C++11的CAS方法: compare_exchange_weak。compare_exchange_weak会比较当前值和期望值,当前值与期望值相等时,修改当前值为设定值,返回true;当前值与期望值不等时,将期望值修改为当前值,返回false。

如果compare_exchange_weak返回false,证明有其它线程更新了栈顶,此时循环会再次尝试压栈,直至压栈成功。

从堆栈弹出数据

常见的错误实现一:

[……]

继续阅读

Read More
| by msbeta | No comments

C++多线程编程-设计并发队列

1、最基础的并发队列

并发队列最直观的实现就是使用互斥锁管理数据同步,向队列中添加数据或者删除数据时,使用互斥锁保证访问的安全性。

如下代码所示,我们基于STL中的链表(List)实现并发队列,队列类的构造函数和析构函数负责创建和销毁互斥锁。

在并发队列中插入数据:

在并发队列中删除数据:

2. 读写互斥的并发队列

在实际的应用场景中,会有这样的场景:假设你有一个很长的队列,从队列中读取数据的线程远远多于写入数据的线程,或者队列读取数据的需求远远大于队列数据写入的需求,如果写入和读取数据使用相同的互斥锁,会大大降低系统的效率。

为了解决这个[……]

继续阅读

Read More
| by msbeta | No comments

一切皆投资

近几个月陆续读完了<小狗钱钱>、<穷爸爸富爸爸>、<时间的朋友>、<七年就是一辈子>和李笑来的专栏<财富自由之路>,对财富、复利、投资有了不少新的认知,也觉得以前的自己好蠢好蠢…

整天睡大觉的现金存款

平时由于工作比较忙碌,很少考虑应该如何管理自己的钱。每个月公司直接把工资打到自己的账户中,然后他们大部分竟然以”活期存款”的形式默默的趟在我的银行账户中,产生着近乎为零的收益。

而今年疫情原因,国家货币大放水,通胀的扩大,纸币在快速的缩水。按照<小狗钱钱>中的计算方法,假设每年的通胀率为6%,你持有的现金的[……]

继续阅读

Read More
| by msbeta | No comments

C++多线程编程-C++ Concurrency in Action

C++ Concurrency in Action可以作为C++在编写优雅多线程应用方面的权威指南。其详细描述了启动新线程到设计复杂的多线程算法和数据结构,在每一章中并发大师Anthony Williams都提供了示例和一些练习和一些独到的见解,这对于从事并发开发的同学会很有帮助。

<<Concurrency in Action>>第一版中文翻译版本的GitHub地址:

https://github.com/xiaoweiChen/Cpp_Concurrency_In_Action

<<Concurrency in Action>&g[……]

继续阅读

Read More
| by msbeta | No comments

C++多线程-GDB调试

1、GDB多线程调试基础

先看一个简单的场景,丈夫和妻子赚钱养家,丈夫每天赚6美元,妻子每天赚3美元,(生活不易,哈哈),它们每天把挣到的钱存到共用账户。C++代码示例如下:

代码编译:

g++ -std=c++11 hard_life.cpp -o hard_life -lpthread -g

运行程序:

进入GDB调试:

1.1 设置断点 break hard_life.cpp:18

GDB设置断点,运行程序:

1.2 查看运行的线程: info threads

查看当前运行的线程:info threads,可以看到当[……]

继续阅读

Read More
| by msbeta | No comments

C++多线程编程-智能指针shared_ptr

1、shared_ptr的引用计数是线程安全的么?

shared_ptr的引用计数是线程安全的。

2、shared_ptr对象是线程安全的么?

shared_ptr对象不是线程安全的。如果多个线程读写同一个shared_ptr对象,需要加锁。注意,这里说的shared_ptr对象本身,而不是shared_ptr所管理的内存。

以下解释shared_ptr对象为什么不是线程安全的?

如下图所示,shared_ptr<Foo> 包含两个成员:指针 ptr(指向堆内存上的Foo对象)和指针ref_count(指向堆内存上的 ref_count 对象)。ref_cou[……]

继续阅读

Read More
| by msbeta | No comments

C++多线程编程-基础入门

1. Hello Word

先从一个简单的多线程程序开始,标准的C++库中提供了对于多线程的支持,实现一个简单的多线程的代码非常容易。

在新线程启动后,主线程会继续执行到main()函数结束,然后退出程序,这时新线程可能还没有被执行。为了保证新线程一定可以被调用执行,需要调用join()函数使得调用线程等待新线程执行完成再退出。

2、std::thread的task参数

新线程的启动是通过构造std::thread对象实现的,std::thread的参数是在线程中要运行的task,最简单的情况下,task是一个void返回值的没有参数的普通函数

事实上,[……]

继续阅读

Read More
| by msbeta | No comments

C++11-shared_ptr使用的两个坑

1、禁止使用一个裸指针创建多个智能指针

先看下如下的代码,会有什么样的问题呢?没错,ptr_1和ptr_2均使用裸指针(raw pointer),指向同一块内存,但它们彼此不相知。

当ptr_2作用域结束时,它会delete关联的裸指针(raw pointer),然后ptr_1的指针就会悬空,成为一个非法值。

同理,当ptr_1作用域结束时,它会delete关联的裸指针(raw pointer),然后ptr_2的指针就会悬空,成为一个非法值。

2. 禁止从栈对象创建shared_ptr

看下面一段代码:

shared_ptr要求与它关联的内存来自[……]

继续阅读

Read More
| by msbeta | No comments

变长数据Features转换为Tensor

ISSUE

从数据集(Dataset)中构造神经网络输入时,遇到同一维度的的Feature元素个数不同的问题,比如:

$$
\text{features} = [[1, 2, 3], [4, 5], [1, 4, 6, 7]]
$$

这种变长的Feature数据在Tensorflow中是不被支持的,当尝试将变长的list转换为Tensor时:

会有如下的报错:

解决的方法就是把各个维度补齐,根据不同的目的补齐的方法不同,常见的就是补零或者重复最后一个元素

补零(Padding With Zeros)

输出:

重复最后的元素(Re[……]

继续阅读

Read More