windows C++-内存管理函数

该文档介绍并发运行时提供的内存管理函数,可帮助你以并发方式分配和释放内存。

并发运行时提供了一个默认计划程序,因此无需在应用程序中创建一个。 由于任务计划程序有助于优化应用程序的性能,如果你刚开始接触并发运行时,建议从使用并行模式库 (PPL) 或异步代理库开始。

并发运行时提供两个内存管理函数,这些函数已经过优化,能以并发方式分配和释放内存块。 concurrency::Alloc 函数通过使用指定的大小来分配内存块。 concurrency::Free 函数释放由 Alloc 分配的内存。

Alloc 函数和 Free 函数是相互依赖的。 仅使用 Free 函数释放通过 Alloc 函数分配的内存。 此外,使用 Alloc 函数分配内存时,仅使用 Free 函数释放该内存。

在从不同的线程或任务分配和释放固定的分配大小时,请使用 Alloc 和 Free 函数。 并发运行时会缓存它从 C 运行时堆分配的内存。 并发运行时为每个运行的线程保存单独的内存缓存;因此,运行时无需使用锁或内存屏障即可管理内存。 当内存缓存被更高频率地访问时,应用程序会更受益于 Alloc 和 Free 函数。 例如,经常调用 Alloc 和 Free 的线程比主要调用 Alloc 或 Free 的线程受益更多。

在使用这些内存管理函数且应用程序使用大量内存的情况下,应用程序可能会比预期更快地进入低内存状态。 因为一个线程缓存的内存块无法用于任何其他线程,所以如果某个线程持有大量内存,则该部分内存不可用。

使用 Alloc 和 Free 提高内存性能

演示如何使用 concurrency::Alloc 和 concurrency::Free 函数提高内存性能。 比较为三种不同类型(每种类型都指定 new 和 delete 运算符)并行地颠倒数组元素所需的时间。

多个线程频繁地同时调用 Alloc 和 Free 时,Alloc 和 Free 函数最有用。 运行时为每个线程保存单独的内存缓存;因此,运行时无需使用锁或内存屏障即可管理内存。

示例:指定 new 和 delete 运算符的类型

下面的示例演示三种类型,每一种都指定 new 和 delete 运算符。 new_delete 类使用 new 和 delete 全局运算符,malloc_free 类使用 C Runtime 的 malloc 和 free 函数,而 Alloc_Free 类使用并发运行时的 Alloc 和 Free 函数。

// A type that defines the new and delete operators. These operators 
// call the global new and delete operators, respectively.
class new_delete
{
public:
   static void* operator new(size_t size)
   {
      return ::operator new(size);
   }
   
   static void operator delete(void *p)
   {
      return ::operator delete(p);
   }

   int _data;
};

// A type that defines the new and delete operators. These operators 
// call the C Runtime malloc and free functions, respectively.
class malloc_free
{
public:
   static void* operator new(size_t size)
   {
      return malloc(size);
   }
   static void operator delete(void *p)
   {
      return free(p);
   }

   int _data;
};

// A type that defines the new and delete operators. These operators 
// call the Concurrency Runtime Alloc and Free functions, respectively.
class Alloc_Free
{
public:
   static void* operator new(size_t size)
   {
      return Alloc(size);
   }
   static void operator delete(void *p)
   {
      return Free(p);
   }

   int _data;
};
示例:swap 和 reverse_array 函数

下面的示例显示 swap 和 reverse_array 函数。 swap 函数在指定的索引处交换数组的内容。 它为临时变量分配堆中的内存。 reverse_array 函数创建一个大数组,并计算并行地多次颠倒该数组所需的时间。

// Exchanges the contents of a[index1] with a[index2].
template<class T>
void swap(T* a, int index1, int index2)
{
   // For illustration, allocate memory from the heap.
   // This is useful when sizeof(T) is large.
   T* temp = new T;
   
   *temp = a[index1];
   a[index1] = a[index2];
   a[index2] = *temp;
   
   delete temp;
}

// Computes the time that it takes to reverse the elements of a 
// large array of the specified type.
template <typename T>
__int64 reverse_array()
{
    const int size = 5000000;
    T* a = new T[size];   
    
    __int64 time = 0;
    const int repeat = 11;

    // Repeat the operation several times to amplify the time difference.
    for (int i = 0; i < repeat; ++i)
    {
        time += time_call([&] {
            parallel_for(0, size/2, [&](int index) 
            {
                swap(a, index, size-index-1); 
            });
        });
    }

    delete[] a;
    return time;
}
示例:wmain 函数

以下示例演示 wmain 函数,该函数计算 reverse_array 函数作用于 new_delete、malloc_free 和 Alloc_Free 类型所需的时间,这三种类型都使用不同的内存分配方案。

int wmain()
{  
   // Compute the time that it takes to reverse large arrays of 
   // different types.

   // new_delete
   wcout << L"Took " << reverse_array<new_delete>() 
         << " ms with new/delete." << endl;

   // malloc_free
   wcout << L"Took " << reverse_array<malloc_free>() 
         << " ms with malloc/free." << endl;

   // Alloc_Free
   wcout << L"Took " << reverse_array<Alloc_Free>() 
         << " ms with Alloc/Free." << endl;
}
完整代码示例 
// allocators.cpp
// compile with: /EHsc 
#include <windows.h>
#include <ppl.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Calls the provided work function and returns the number of milliseconds 
// that it takes to call that function.
template <class Function>
__int64 time_call(Function&& f)
{
   __int64 begin = GetTickCount();
   f();
   return GetTickCount() - begin;
}

// A type that defines the new and delete operators. These operators 
// call the global new and delete operators, respectively.
class new_delete
{
public:
   static void* operator new(size_t size)
   {
      return ::operator new(size);
   }
   
   static void operator delete(void *p)
   {
      return ::operator delete(p);
   }

   int _data;
};

// A type that defines the new and delete operators. These operators 
// call the C Runtime malloc and free functions, respectively.
class malloc_free
{
public:
   static void* operator new(size_t size)
   {
      return malloc(size);
   }
   static void operator delete(void *p)
   {
      return free(p);
   }

   int _data;
};

// A type that defines the new and delete operators. These operators 
// call the Concurrency Runtime Alloc and Free functions, respectively.
class Alloc_Free
{
public:
   static void* operator new(size_t size)
   {
      return Alloc(size);
   }
   static void operator delete(void *p)
   {
      return Free(p);
   }

   int _data;
};

// Exchanges the contents of a[index1] with a[index2].
template<class T>
void swap(T* a, int index1, int index2)
{
   // For illustration, allocate memory from the heap.
   // This is useful when sizeof(T) is large.
   T* temp = new T;
   
   *temp = a[index1];
   a[index1] = a[index2];
   a[index2] = *temp;
   
   delete temp;
}

// Computes the time that it takes to reverse the elements of a 
// large array of the specified type.
template <typename T>
__int64 reverse_array()
{
    const int size = 5000000;
    T* a = new T[size];   
    
    __int64 time = 0;
    const int repeat = 11;

    // Repeat the operation several times to amplify the time difference.
    for (int i = 0; i < repeat; ++i)
    {
        time += time_call([&] {
            parallel_for(0, size/2, [&](int index) 
            {
                swap(a, index, size-index-1); 
            });
        });
    }

    delete[] a;
    return time;
}

int wmain()
{  
   // Compute the time that it takes to reverse large arrays of 
   // different types.

   // new_delete
   wcout << L"Took " << reverse_array<new_delete>() 
         << " ms with new/delete." << endl;

   // malloc_free
   wcout << L"Took " << reverse_array<malloc_free>() 
         << " ms with malloc/free." << endl;

   // Alloc_Free
   wcout << L"Took " << reverse_array<Alloc_Free>() 
         << " ms with Alloc/Free." << endl;
}

对于具有四个处理器的计算机,本示例生成以下示例输出。 

Took 2031 ms with new/delete.
Took 1672 ms with malloc/free.
Took 656 ms with Alloc/Free.

在此示例中,使用 Alloc 和 Free 函数的类型提供最佳的内存性能,因为我们对 Alloc 和 Free 函数进行了优化,以便频繁地分配和释放来自多个线程的内存块。

编译代码

复制示例代码,并将它粘贴到 Visual Studio 项目中,或粘贴到名为 allocators.cpp 的文件中,再在 Visual Studio 命令提示符窗口中运行以下命令。

cl.exe /EHsc allocators.cpp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值