Compartilhar via


Como usar Alloc e Free para melhorar o desempenho da memória

Este documento mostra como usar as funções de concurrency::Alloc e de concurrency::Free para melhorar o desempenho de memória. Compara o tempo necessário para inverter em paralelo os elementos de uma matriz para três tipos diferentes cada um que especifica os operadores de new e de delete .

As funções de Alloc e de Free são mais úteis quando vários threads chamam frequentemente Alloc e Free. O tempo de execução contém um cachê de memória separado para cada thread; consequentemente, o tempo de execução gerencia a memória sem o uso de bloqueios ou de barreiras de memória.

Exemplo

O exemplo a seguir mostra três tipos que cada um especifica os operadores de new e de delete . A classe de new_delete usa new e os operadores globais de delete , a classe de malloc_free usa o tempo de execução malloc C e funções de livre , e a classe de Alloc_Free usa o tempo de execução Alloc de simultaneidade e funções de 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;
};

O exemplo a seguir mostra as funções swap e reverse_array. A função de swap troca o conteúdo da matriz de índices especificados. Aloca memória do heap para a variável temporário. A função de reverse_array cria uma matriz e computa o tempo necessário para inverter em paralelo que matriz várias vezes.

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

O exemplo a seguir mostra a função de wmain , que calcula o tempo necessário para que a função de reverse_array atue em new_delete, em malloc_free, e em tipos de Alloc_Free , que usa um esquema de alocação de memória diferente.

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

O exemplo completo a seguir.

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

Este exemplo gerencia a seguinte saída de exemplo para um computador que tem quatro processadores.

  

Neste exemplo, o tipo usando as funções de Alloc e de Free fornece desempenho melhor de memória porque as funções de Alloc e de Free são otimizadas frequentemente atribuindo e liberando bloqueios de memória de vários threads.

Compilando o código

Copie o código de exemplo e cole-o em um projeto do Visual Studio, ou cole-o em um arquivo chamado allocators.cpp e execute o comando a seguir em uma janela de prompt de comando do Visual Studio.

cl.exe /EHsc allocators.cpp

Consulte também

Referência

Função Alloc

Função livre

Conceitos

Funções de gerenciamento da memória