방법: Alloc 및 Free를 사용하여 메모리 성능 개선

이 문서에서는 동시성::Alloc동시성::Free 함수를 사용하여 메모리 성능을 향상시키는 방법을 보여 줍니다. 각각 및 delete 연산자를 지정 new 하는 세 가지 형식에 대해 배열의 요소를 병렬로 되돌리는 데 필요한 시간을 비교합니다.

및 함수는 Alloc 여러 스레드가 둘 다 Alloc 호출하는 경우가 많을 Free때 가장 Free 유용합니다. 런타임은 각 스레드에 대해 별도의 메모리 캐시를 보유합니다. 따라서 런타임은 잠금 또는 메모리 장벽을 사용하지 않고 메모리를 관리합니다.

예: 새 연산자와 삭제 연산자를 지정하는 형식

다음 예제에서는 각각 및 delete 연산자를 지정하는 세 가지 형식을 new 보여줍니다. 클래스는 전역 newdelete 연산자를 사용하고, malloc_free 클래스는 new_delete 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;
};

예: 스왑 및 reverse_array 함수

다음 예제에서는 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;
}

예: w기본 함수

다음 예제에서는 함수가 wmain 동작new_deletemalloc_free하는 데 필요한 reverse_array 시간 및 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;
}

이 예제에서는 4개의 프로세서가 있는 컴퓨터에 대해 다음 샘플 출력을 생성합니다.

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

이 예제에서 함수와 Free 함수를 사용하는 Alloc 형식은 여러 스레드에서 메모리 블록을 자주 할당하고 해제하는 데 최적화되어 있으므로 AllocFree 최상의 메모리 성능을 제공합니다.

코드 컴파일

예제 코드를 복사하여 Visual Studio 프로젝트에 붙여넣거나 이름이 지정된 allocators.cpp 파일에 붙여넣은 다음 Visual Studio 명령 프롬프트 창에서 다음 명령을 실행합니다.

cl.exe /EHsc allocators.cpp

참고 항목

메모리 관리 함수
Alloc 함수
Free 함수