다음을 통해 공유


방법: 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_delete, malloc_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;
}

프로세서가 4개인 컴퓨터에 대해 이 예제를 실행하면 다음과 같은 샘플 결과가 출력됩니다.

  

AllocFree 함수는 여러 스레드에서 메모리 블록을 자주 할당하고 해제하기 위해 최적화되어 있으므로 이 예제에서는 AllocFree 함수를 사용하는 형식의 메모리 성능이 가장 좋습니다.

코드 컴파일

예제 코드를 복사하여 Visual Studio 프로젝트 또는 allocators.cpp 파일에 붙여넣고 Visual Studio 명령 프롬프트 창에서 다음 명령을 실행합니다.

cl.exe /EHsc allocators.cpp

참고 항목

참조

Alloc 함수

Free 함수

개념

메모리 관리 함수