2013-01-21 18 views
43

Kilitlenmeden veri yapıları ve zamanlama kodu uygulandığında, derleyicinin optimizasyonlarını bastırmak genellikle gereklidir. Normalde insanlar asm volatile'u memory kullanarak clobber listesinde yaparlar, ancak bazen sadece asm volatile veya sadece asm clobbering hafızasını görürsünüz.Asm, asm volatile ve clobbering belleği arasındaki fark

Bu farklı ifadelerin kod oluşturma üzerinde (özellikle taşınabilir olma olasılığı düşük olan GCC'de) ne gibi bir etkisi vardır? ..

asm (""); // presumably this has no effect on code generation 
asm volatile (""); 
asm ("" ::: "memory"); 
asm volatile ("" ::: "memory"); 
+0

Birisi çok yakın çevresinde uzakta oyalanamam görünüyor metal :-) (Ve başka bir yerde, @Mysticial gülünç bir şekilde ayrıntılı bir cevapta yazıyor ...) –

cevap

39

"Extended Asm" page in the GCC documentation bakınız oluşturur olup.

Sen asm sonra anahtar kelimeleri volatile yazarak silinmesini bir asm talimat önleyebilir. [...] volatile anahtar kelimesi, talimatın önemli yan etkileri olduğunu gösterir. GCC, ulaşılabilirse volatile asm'yi silmeyecektir. herhangi bir çıkış değişken olmaksızın

ve

bir asm talimat, bir uçucu asm talimat aynı şekilde muamele edilir.senin örneklerinden

Yok çıktı operandları belirtilen yüzden asm ve asm volatile formları aynı şekilde davranır var: (ulaşılamaz olduğunu kanıtladı sürece) onlar silinemez kodda bir nokta oluşturmak.

Bu, hiçbir şey yapmamakla aynı şey değildir. Kod oluşturma işlemini değiştiren bir asm modelinin bir örneği için bkz. this question - bu örnekte, 1000 kez döngüdeki bir döngüye geçen kod, döngünün 16 yinelemesini bir kerede hesaplayan kod haline getirilir; Ancak, döngünün içinde bir asm bulunması, optimizasyonu engeller (asm 1000 defaya ulaşılmalıdır). Bu GCC tutmak neden olur

:

"memory" clobber GCC herhangi bellek okumak veya asm bloğu tarafından yazılmış keyfi olabileceğini varsayar, böylece karşıya yükler veya mağaza yeniden sıralanması gelen derleyici önleyecektir yapar bellek değerleri, assembler talimatı boyunca kayıtlarda önbelleğe alınır ve bu belleğe depoları veya yükleri optimize etmez.

(Gerçi, başka CPU göre yükleri ve depolar yeniden sıralanması bir CPU engellemez;. Bunun için gerçek bellek bariyer talimatlara ihtiyaç)

+0

Aslında bu çok ilginç, gcc'nin "asm" bloklarını uçucu olmayan çıktılar olarak algılayışının benim bilgimde büyük bir boşluk olduğunu fark etmiyor. – jleahy

+0

Yani 'volatile' = performans katili ne bağlamda kullanılırsa kullanılsın (değişken veya asm). 'Goto' anahtar kelimesiyle dosyalayın - sadece kesinlikle gerekli olduğunda kullanın. – etherice

8

da asm ("") hiçbir şey yapmaz (veya en azından, bir şey yapmak zorunda değil

asm volatile ("") yapar şey

asm ("" ::: "memory"):

Sadece başvuru için, bu ilginç varyasyonlar Basit bir derleyici çittir. önceki gibi. volatile anahtar sözcüğü derleyiciye bu derleme bloğunu taşımasına izin verilmediğini bildirir. Örneğin, derleyici, giriş değerlerinin her çağrıda aynı olduğuna karar verirse, bir döngüden kaldırılabilir. Derleyicinin, yerleşimi optimize etmeyi denemek için derlemenin yeterli olduğunu anlayacağı konusunda hangi koşulların sağlanacağından emin değilim, ancak volatile anahtar sözcüğü bunu tamamen bastırıyor. Derleyici, beyan edilen girdi veya çıktı içermeyen bir asm ifadesini taşımayı denediğinde çok şaşırırdım.

Ayrıca, volatile, ayrıca, çıktı değerlerinin kullanılmadığına karar verirse, derleyicinin ifadeyi silmesini önler. Bu yalnızca çıkış değerleri olsa, ancak asm ("" ::: "memory") için geçerli değildir.

+6

Matthew Slattery'nin cevabı, “uçucu uçucu (" ")' nin hiçbir şey yapmamakla aynı şey olmadığını gösteriyor. derleyici optimizasyonu üzerinde büyük etkileri vardır. Aynı performans sonuçları, bir derleyici çit olarak “asm volatile (" ":::" memory ")' nin kullanılması için geçerli olacaktır. – etherice

+0

Derleyici, derleme dilini anlamıyor! – curiousguy

+1

@curiousguy no, ancak bir "asm" bloğunun girdiyi/çıktısını bildirdiği zaman, bunu kaydeden derleyiciye bağlı olup olmadığını ve hangilerinin değiştireceğini söyler ve bu nedenle derleyici, eğer varsa, bazı hesaplamaları değiştirebilir Giriş/çıkışları etkilemez. –

1

Sadece Kevin Ballard'ın yanıtı için Visual Studio 2010, aynısını yapmak için _ReadBarrier(), _WriteBarrier() ve _ReadWriteBarrier() sunuyor (VS2010, 64 bit uygulamalar için satır içi düzeneğe izin vermiyor).

Bunlar, hiçbir komut üretmez, ancak derleyicinin davranışını etkiler. Güzel bir örnek here

MemoryBarrier() lock or DWORD PTR [rsp], 0