SORU
22 Aralık 2014, PAZARTESİ


Modern C performans için ücretsiz alabilirsiniz?

Bazen sadece derleme C 98 kod bile C 11/14 sana bir performans artışı elde edildi. Gerekçe genellikle rvalue kurucular otomatik olarak oluşturulan bazı durumlarda veya STL parçası olarak hareket semantiği çizgisinde. Şimdi bu durumda daha önce aslında zaten rvt li veya benzer derleyici en iyi duruma getirme tarafından işlenen olup olmadığını merak ediyorum.

Benim sorum ise bana, değişiklik olmadan, daha hızlı bir derleyici yeni bir dil özelliklerini destekleyen kullanarak çalışan C 98 kod parçasının gerçek bir örnek verebilirseniz. Anlıyorum bu bir standart uyumlu derleyici değil zorunlu kıldığı kopya elision ve sadece bu nedenle hareket semantiği getireceği konusunda hızlı, ama ben görmek isterim bir daha az patolojik vaka, eğer olacak.

EDİT: Sadece açık olmasını, ben değilim soran olsun yeni Derleyiciler daha hızlıdır eski derleyici, daha ziyade varsa kodu sayede ekleme -std=c 14 benim derleyici bayrakları olurdu daha hızlı koşun (önlemek kopya, ama eğer sen-ebilmek gelmek yukarıya ile başka bir şey dışında hareket semantiği, ben ilgilenir, çok)

CEVAP
22 Aralık 2014, PAZARTESİ


C 11 C 03 derleyici yeniden uygulamanın kalitesi hemen hemen ilgisiz performans artışı sınırlandırılmamış neden olabilir 5 Genel kategori farkındayım. Bu hareket anlam çeşitleri vardır.

std::vector ayrılacak

struct bar{
  std::vector<int> data;
};
std::vector<bar> foo(1);
foo.back().data.push_back(3);
foo.reserve(10); // two allocations and a delete occur in C  03

her zaman foo'nin tampon C bar 9 *Her kopyaladı. 03 yeniden

C 11 bunun yerine, temelde serbest olan bar::datas, hareket eder.

Bu durumda, bu std kap vector içinde en iyi duruma getirme kullanır. C 11 her durumda, aşağıda std konteynır kullanımı move verimli anlambilim C nesneleri olduklarından sadece "otomatik olarak" ne zaman, derleyici yükseltme. std bir kap içeren bloke etme nesneleri de otomatik move geliştirilmiş kurucular miras.

NRVO hatası

NRVO (dönüş değeri optimizasyon olarak adlandırılır), C 03 kopyalayın düşüyor C 11 başarısız olduğunda geri hareket düşüyor. NRVO başarısızlıkları kolay

std::vector<int> foo(int count){
  std::vector<int> v; // oops
  if (count<=0) return std::vector<int>();
  v.reserve(count);
  for(int i=0;i<count;  i)
    v.push_back(i);
  return v;
}

hatta:

std::vector<int> foo(bool which) {
  std::vector<int> a, b;
  // do work, filling a and b, using the other for calculations
  if (which)
    return a;
  else
    return b;
}

Üç değeri dönüş değeri var, ve işlevi içinde iki farklı değerler. Elision işlevi değerleri " dönüş değeri, ama birbirleriyle değil. ile birleşti sağlar İkisi de birbirleri ile birleştirme olmadan dönüş değeri ile birleştirilemez.

Temel sorun NRVO elision kırılgan ve return site değil yakın değişikliklerle kod aniden hiçbir tanı ile bu noktada büyük bir performans indirimleri yayılan olabilir. En NRVO arıza gibi durumlarda C 11 C 03 kopya ile biter iken move ile biter.

Bir işlev bağımsız değişkeni dönüyor

Elision da imkansız burada

std::set<int> func(std::set<int> in){
  return in;
}

bu ucuz C 11: C 03 kopyayı önlemek için bir yol yoktur. Parametre ve dönüş değeri ömür boyu ve konumu çağıran kod tarafından yönetilen olduğundan, dönüş değeri ile elided, olamaz, işlev için bağımsız değişken.

Ancak, C 11, birinden diğerine hareket edebilir. (Daha az oyuncak bir örnekte, bir şey set) yapılabilir.

push_back insert

Konteynerler olmaz içine nihayet elision: ama C 11 aşırı rvalue kopyalarını kaydeder Ekle operatörleri, hareket.

struct whatever {
  std::string data;
  int count;
  whatever( std::string d, int c ):data(d), count(c) {}
};
std::vector<whatever> v;
v.push_back( whatever("some long string goes here", 3) );

C 03 a geçici olarak whatever oluşturulur, daha sonra vektör v içine kopyalanır. 2 std::string tamponlar, aynı veri her ile ayrılır ve atılır.

C 11 whatever geçici oluşturulur. whatever&& push_back aşırı sonra 34* *vektör içine geçici moveler. std::string bir arabellek ayrılır ve vektör taşındı. std::string boş atılır.

Atama

@Jarod42 cevabı aşağıda çalınmış.

Olamaz atama ile ortaya çıkar, ama hareket Elision.

std::set<int> some_function();

std::set<int> some_value;

// code

some_value = some_function();

burada some_function elide için bir aday döndürür, ama doğrudan bir nesne oluşturmak için kullanılan çünkü, elided olamaz. C 03, yukarıdaki geçici some_value içine kopyalanan içeriği ile sonuçlanır. C 11, temelde ücretsiz some_value taşınır.


Yukarıda tam etki için, sizin için hareket yapıcılar ve atama sentezleyip bir derleyici gerekir.

MSVC 2013 std kaplarda hareket kurucular uygular, ama kendi türlerini devam kurucular sentez değildir.

Türleri std::vectors ve benzeri içeren MSVC2013, ama MSVC2015 onları almaya başlayacak gibi gelişmeler alamadım.

çınlama ve gcc uzun zamandan beri örtülü hareket kurucular hayata geçirdik. Intel 2013 derleyici -Qoption,cpp,--gen_move_operations (MSVC2013 ile çapraz uyumlu olması için bir çaba varsayılan olarak yapmazlar) iletirseniz hareket kurucular örtülü nesil destekleyecektir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Jaclyn W

    Jaclyn W

    5 Mayıs 2006
  • jpmkm1

    jpmkm1

    4 NİSAN 2008
  • Tinkernut

    Tinkernut

    28 Aralık 2006