Aracılığıyla paylaş


Nasıl yapılır: Bellek Performansını Artırmak için Alloc ve Free Kullanma

Bu belgede bellek performansını geliştirmek için eşzamanlılık::Alloc ve eşzamanlılık::Serbest işlevlerin nasıl kullanılacağı gösterilmektedir. Her biri ve new işleçlerini belirten delete üç farklı tür için bir dizinin öğelerini paralel olarak ters çevirmek için gereken süreyi karşılaştırır.

Alloc ve Free işlevleri en çok birden çok iş parçacığı hem hem de AllocFree'yi çağırdığında kullanışlıdır. Çalışma zamanı her iş parçacığı için ayrı bir bellek önbelleği tutar; bu nedenle çalışma zamanı, kilitler veya bellek engelleri kullanmadan belleği yönetir.

Örnek: Yeni ve silme işleçlerini belirten türler

Aşağıdaki örnekte her biri ve new işleçlerini delete belirten üç tür gösterilmektedir. new_delete sınıfı genel new ve delete işleçleri, malloc_free sınıfı C Runtime malloc ve free işlevlerini, sınıfı ise Alloc_Free Eşzamanlılık Çalışma Zamanı Alloc ve Free işlevlerini kullanır.

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

Örnek: swap ve reverse_array işlevleri

Aşağıdaki örnekte ve swap işlevleri gösterilmektedirreverse_array. İşlev, swap belirtilen dizinlerde dizinin içeriğini değiştirir. Geçici değişken için yığından bellek ayırır. reverse_array işlevi büyük bir dizi oluşturur ve bu diziyi paralel olarak birkaç kez ters çevirmek için gereken süreyi hesaplar.

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

Örnek: wmain işlevi

Aşağıdaki örnekte, işlevin wmain , reverse_arrayve türleri üzerinde new_deleteişlem yapmak için malloc_free gereken süreyi hesaplayan ve Alloc_Free her biri farklı bir bellek ayırma düzeni kullanan işlevi gösterilmektedir.

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

Tam kod örneği

Tam örnek aşağıda verilmiştir.

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

Bu örnek, dört işlemcisi olan bir bilgisayar için aşağıdaki örnek çıkışı oluşturur.

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

Bu örnekte, ve işlevlerini kullanan Alloc tür en iyi bellek performansını sağlar çünkü Free ve Alloc işlevleri birden çok iş parçacığından bellek bloklarını sık sık ayırma ve boşaltma için iyileştirilmiştir.Free

Kod Derleniyor

Örnek kodu kopyalayıp bir Visual Studio projesine yapıştırın veya adlı allocators.cpp bir dosyaya yapıştırın ve ardından bir Visual Studio Komut İstemi penceresinde aşağıdaki komutu çalıştırın.

cl.exe /EHsc allocators.cpp

Ayrıca bkz.

Bellek Yönetimi İşlevleri
Alloc İşlevi
Free İşlevi