共用方式為


如何:使用 Alloc 和 Free 改善記憶體效能

本文件將示範如何使用 concurrency::Allocconcurrency::Free 函式來改善記憶體效能。 它會針對三個指定 newdelete 運算子的不同型別,比較以平行方式反轉陣列元素所需的時間。

當多個執行緒經常同時呼叫 AllocFree 時,AllocFree 函式最有用。 執行階段會為每個執行緒保留一個獨立的記憶體快取;因此,執行階段在管理記憶體時無須使用鎖定或記憶體屏障。

範例

下列範例顯示三個指定 newdelete 運算子的型別。 new_delete 類別會使用全域 new 和 delete 運算子、malloc_free 類別會使用 C 執行階段 mallocfree 函式,而 Alloc_Free 類別會使用並行執行階段 AllocFree 函式。

// 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;
};

下列範例顯示 swapreverse_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 函式,此函式會計算針對 new_deletemalloc_freeAlloc_Free 型別 (每個型別都使用不同的記憶體配置) 執行 reverse_array 函式所需的時間。

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;
}

這個範例會在配備四個處理器的電腦上產生下列範例輸出。

  

在這個範例中,使用 AllocFree 函式的型別會提供最佳的記憶體效能,因為 AllocFree 函式已針對多個執行緒中經常配置和釋放的記憶體區塊最佳化。

編譯程式碼

請複製範例程式碼,並將它貼在 Visual Studio 專案中,或貼在名為 allocators.cpp 的檔案中,然後在 Visual Studio 的 [命令提示字元] 視窗中執行下列命令。

cl.exe /EHsc allocators.cpp

請參閱

參考

Alloc 函式

Free 函式

概念

記憶體管理函式