18.3 内存池概念、代码实现和详细分析

一:内存池的概念和实现原理概述

malloc:内存浪费,频繁分配小块内存,浪费更加明显。

“内存池”要解决什么问题?

1、减少malloc()的次数,减少malloc()调用次数就意味着减少对内存的浪费
2、减少malloc()的调用次数,是否能够提高程序运行效率?
   会有一些速度和效率上的提升,但是提升不明显。

“内存池”实现原理:

1、使用malloc申请一个大块内存,当有分配需求的时候,从这一大块内存中一点点的进行分配,当这一大块内存分配快占满的时候了,再用malloc申请一大块内存,再一点点进行分配。
2、减少内存浪费,提高运行效率。

二:针对一个类的内存池实现演示代码

针对一个类的内存池A,A* pa = new A(),delete pa; 用内存池的手段实现new、delete对象。

1、内存池的operator new实现



void* A::operator new(size_t size)
{
	A* ptmplink;
	if (m_freePosition == nullptr)
	{
		//为空,要申请一大块内存
		size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存
		m_freePosition = reinterpret_cast<A*>(new char[realsize]);  //传统new,调用系统底层的malloc
		ptmplink = m_freePosition;

		//把分配出来的这一大块内存(5下块),彼此要链起来,供后续使用
		for (; ptmplink != &m_freePosition[m_sTrunkCount - 1]; ptmplink++)
		{
			ptmplink->next = ptmplink + 1;
		}
		ptmplink->next = nullptr;
		++m_iMallocCount;
	}
	ptmplink = m_freePosition;
	m_freePosition = m_freePosition->next;
	++m_iCount;
	return ptmplink;
}

2、内存池的operator delete实现


在这里插入图片描述

void A::operator delete(void* phead)
{
	(static_cast<A*>(phead))->next = m_freePosition;
	m_freePosition = static_cast<A*>(phead);
}

3、完整代码

#include<ctime>
#include <iostream>

using namespace std;

//#define MYMEMPOOL 1
class A
{
public:
	static void* operator new(size_t size);
	static void operator delete(void* phead);
	static int m_iCount;  //分配计数统计,每new一次,就统计一次
	static int m_iMallocCount;  //每malloc一次,就统计一次

private:
	A* next;
	static A* m_freePosition;  //总是指向一块可以分配出去的内存首地址
	static int m_sTrunkCount;  //一次分配多少倍的该类内存
};

int A::m_iCount = 0;
int A::m_iMallocCount = 0;
A* A::m_freePosition = nullptr;
int A::m_sTrunkCount = 5;  //一次分配5倍的该类内存作为内存池的大小

void* A::operator new(size_t size)
{
#ifdef MYMEMPOOL
	A* ppoint = (A*)malloc(size);
	++m_iMallocCount;
	++m_iCount;
	return ppoint;
#else
	A* ptmplink;
	if (m_freePosition == nullptr)
	{
		//为空,要申请一大块内存
		size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存
		m_freePosition = reinterpret_cast<A*>(new char[realsize]);  //传统new,调用系统底层的malloc
		ptmplink = m_freePosition;

		//把分配出来的这一大块内存(5下块),彼此要链起来,供后续使用
		for (; ptmplink != &m_freePosition[m_sTrunkCount - 1]; ptmplink++)
		{
			ptmplink->next = ptmplink + 1;
		}
		ptmplink->next = nullptr;
		++m_iMallocCount;
	}
	ptmplink = m_freePosition;
	m_freePosition = m_freePosition->next;
	++m_iCount;
	return ptmplink;
#endif
}

void A::operator delete(void* phead)
{
#ifdef MYMEMPOOL 
	free(phead);
	return;
#else
	(static_cast<A*>(phead))->next = m_freePosition;
	m_freePosition = static_cast<A*>(phead);
#endif
}

void func()
{
	clock_t start, end;  //包含头文件#include<ctime>
	start = clock();
	for (size_t i = 0; i < 500'0000; i++)
	{
		A* pa = new A();
	}
	end = clock();
	cout << "申请分配内存的次数为:" << A::m_iCount << ";实际malloc的次数为:" << A::m_iMallocCount << endl;
	cout << "用时(毫秒):" << end - start << endl;
}


int main(int argc, const char* argv[])
{
	func();
}

三:内存池代码后续说明

#include<ctime>
#include <iostream>

using namespace std;

//#define MYMEMPOOL 1
class A
{
public:
	static void* operator new(size_t size);
	static void operator delete(void* phead);
	static int m_iCount;  //分配计数统计,每new一次,就统计一次
	static int m_iMallocCount;  //每malloc一次,就统计一次

private:
	A* next;
	static A* m_freePosition;  //总是指向一块可以分配出去的内存首地址
	static int m_sTrunkCount;  //一次分配多少倍的该类内存
};

int A::m_iCount = 0;
int A::m_iMallocCount = 0;
A* A::m_freePosition = nullptr;
int A::m_sTrunkCount = 5;  //一次分配5倍的该类内存作为内存池的大小

void* A::operator new(size_t size)
{
#ifdef MYMEMPOOL
	A* ppoint = (A*)malloc(size);
	++m_iMallocCount;
	++m_iCount;
	return ppoint;
#else
	A* ptmplink;
	if (m_freePosition == nullptr)
	{
		//为空,要申请一大块内存
		size_t realsize = m_sTrunkCount * size;  //申请m_sTrunkCount这么多倍的内存
		m_freePosition = reinterpret_cast<A*>(new char[realsize]);  //传统new,调用系统底层的malloc
		ptmplink = m_freePosition;

		//把分配出来的这一大块内存(5下块),彼此要链起来,供后续使用
		for (; ptmplink != &m_freePosition[m_sTrunkCount - 1]; ptmplink++)
		{
			ptmplink->next = ptmplink + 1;
		}
		ptmplink->next = nullptr;
		++m_iMallocCount;
		printf("%s\n", "---------------------");
	}
	ptmplink = m_freePosition;
	m_freePosition = m_freePosition->next;
	++m_iCount;
	return ptmplink;
#endif
}

void A::operator delete(void* phead)
{
#ifdef MYMEMPOOL 
	free(phead);
	return;
#else
	(static_cast<A*>(phead))->next = m_freePosition;
	m_freePosition = static_cast<A*>(phead);
#endif
}

void func()
{
	clock_t start, end;  //包含头文件#include<ctime>
	start = clock();
	for (size_t i = 0; i < 15; i++)
	{
		A* pa = new A();
		printf("%p\n", pa);
	}
	end = clock();
	printf("%s\n", "---------------------");
	cout << "申请分配内存的次数为:" << A::m_iCount << ";实际malloc的次数为:" << A::m_iMallocCount << endl;
	cout << "用时(毫秒):" << end - start << endl;
}


int main(int argc, const char* argv[])
{
	func();
}

此代码的delete方法并没有释放内存,也没有内存泄漏,申请的内存可重复使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现FFT运算器需要经过以下步骤: 1. 确定FFT的参数:FFT的点数N,蝶形运算的级数M。 2. 设计蝶形运算单元:蝶形运算单元是FFT的基本运算单元,可以采用Butterfly结构或Twiddle结构。 3. 设计FFT的流水线结构:FFT运算器需要流水线结构才能满足高速运算的需求。 4. 编写Verilog代码:根据设计好的蝶形运算单元和FFT流水线结构,编写Verilog代码。 以下是一个简单的FFT运算器的Verilog代码实现示例: ``` module fft ( input clk, // 时钟信号 input rst, // 复位信号 input [15:0] x_in[N], // 输入信号 output reg [15:0] x_out[N] // 输出信号 ); parameter N = 16; // FFT点数 parameter M = 4; // FFT级数 reg [15:0] x[N]; // 内部寄存器 reg [15:0] w[N/2]; // 旋转因子 reg [15:0] tw[N/2][M-1]; // Twiddle因子 // 初始化旋转因子和Twiddle因子 initial begin for (int i = 0; i < N/2; i = i + 1) begin w[i] = $realtobits(cos(2*PI*i/N)); tw[i][0] = $realtobits(cos(2*PI*i/N)); tw[i][1] = $realtobits(cos(2*PI*i/N/2)); tw[i][2] = $realtobits(cos(2*PI*i/N/4)); end end // FFT流水线结构 always @(posedge clk) begin if (rst) begin for (int i = 0; i < N; i = i + 1) begin x[i] <= 0; end end else begin // 输入数据 for (int i = 0; i < N; i = i + 1) begin x[i] <= x_in[i]; end // 蝶形运算 for (int n = 0; n < M; n = n + 1) begin int b = 1 << n; for (int i = 0; i < N; i = i + 1) begin if ((i & b) == 0) begin int j = i + b; reg [15:0] t = x[j] * w[i%(N/2)]; x[j] = x[i] - t; x[i] = x[i] + t; end end end // 输出数据 for (int i = 0; i < N; i = i + 1) begin x_out[i] <= x[i]; end end end endmodule ``` 在这个代码中,我们定义了FFT的点数N和级数M,以及输入和输出信号的宽度。我们还定义了内部寄存器和旋转因子以及Twiddle因子,并在initial块中初始化了它们。在always块中,我们实现了FFT的流水线结构,包括输入数据、蝶形运算和输出数据。具体实现过程可以参考代码中的注释。 需要注意的是,以上示例代码实现的是一个16点FFT运算器,若需要实现其他点数的FFT运算器,需要相应地修改代码中的参数。另外,为了简化代码,该示例中使用了固定的旋转因子和Twiddle因子,实际应用中需要根据FFT的点数和级数进行计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值