다음을 통해 공유


방법: 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개인 컴퓨터에 대해 이 예제를 실행하면 다음과 같은 샘플 결과가 출력됩니다.

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

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

코드 컴파일

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

cl.exe /EHsc allocators.cpp

참고 항목

참조

Alloc 함수

Free 함수

기타 리소스

메모리 관리 함수