2012-07-15 20 views
7

Kalifiye işaretçileri kısıtlamayı denedim ve bir sorunla karşılaştım. Aşağıdaki program sadece sorunu göstermek için basit bir işlemdir.İmleci ve satır işaretini kısıtla

calc_function birbirleriyle yüzden "SHALL" değil takma sınırlıdır üç işaretçileri kullanır. Visual Studio'da bu kodu derlerken, işlev satır içi olacak, bu nedenle Visual Studio 2010, niteleyicileri yok saymaz. Satırları devre dışı bırakırsam, kod altı kat daha hızlı çalışır (2200 ms'den 360 ms'ye kadar). Ancak, tüm projede ya da tüm dosyada satır içi dizilimi devre dışı bırakmak istemiyorum (çünkü bu, örneğin, tüm alıcılar ve ayarlayıcılarda, korkunç olabilecek genel giderler olarak adlandırılacaktır).

(tek çözüm sadece bu işlevin satır içi uygulaması devre dışı bırakmak olabilir mi?) Ben anlatmaya çalışmak geçici üstte ve iç döngüde hem işlevinde nitelikli işaretçileri kısıtlamak oluşturmaya çalıştık

Derleyici, bir takma ad olmadığını, ancak derleyicinin bana inanmayacağını ve işe yaramayacağını vaat ediyorum. Ayrıca, derleyici ayarlarını değiştirmeyi denedim, ancak çalışmayı bulmuş olduğum tek şey, satır içi karakteri devre dışı bırakmak.

Bu optimizasyon problemini çözmek için bazı yardımları takdir ediyorum.

Programı çalıştırmak için (trueeasemode) 0 1000 2000 argümanını kullanmayı unutma. Userinput/program argümanlarının kullanımı, derleyicinin var olup olmadığına veya neden olup olmadığına emin olmamalıdır. t işaretçileri a, b ve c arasında hizalama. Eğer __declspec(noinline) ile işlev bildirimi varsa

#include <cstdlib> 
#include <cstdio> 
#include <ctime> 

// Data-table where a,b,c will point into, so the compiler cant know if they alias. 
const size_t listSize = 10000; 
int data[listSize]; 

//void calc_function(int * a, int * b, int * c){ 
void calc_function(int *__restrict a, int *__restrict b, int *__restrict c){ 
    for(size_t y=0; y<1000*1000; ++y){ // <- Extra loop to be able to messure the time. 
     for(size_t i=0; i<1000; ++i){ 
      *a += *b; 
      *c += *a; 
     } 
    } 
} 
int main(int argc, char *argv[]){ // argv SHALL be "0 1000 2000" (with no quotes) 
    // init 
    for(size_t i=0; i<listSize; ++i) 
     data[i] = i; 

    // get a, b and c from argv(0,1000,2000) 
    int *a,*b,*c; 
    sscanf(argv[1],"%d",&a); 
    sscanf(argv[2],"%d",&b); 
    sscanf(argv[3],"%d",&c); 
    a = data + int(a); // a, b and c will (after the specified argv) be, 
    b = data + int(b); // a = &data[0], b = &data[1000], c = &data[2000], 
    c = data + int(c); // So they will not alias, and the compiler cant know. 

    // calculate and take time 
    time_t start = clock(); 
     funcResticted(a,b,c); 
    time_t end = clock(); 
    time_t t = (end-start); 
    printf("funcResticted  %u (microSec)\n", t); 

    system("PAUSE"); 
    return EXIT_SUCCESS; 
} 
+1

+1. Biçim belirtecinden şikayet etmemeyi tercih edeceğim. Not; 'clock'' time_t' değil, 'time_t' döndürür. – Hurkyl

+1

İşlev çağrısını, ofsetlerin yeterince büyük olduğunu kontrol ederek koruyun. Muhtemelen, kullandığınız bilgisayar korsanlığı yerine, gerçek 'int' değişkenlerini saklamak gerekir. – Hurkyl

+0

@Hurkyl Ben clock_t ve time_t aynı şey için hem typedefs olduğunu düşündüm, ama siz haklısınız. (Btw, soru mesajımı nasıl düzenlerim?) – Boll

cevap

3

, onu inlined gereken zorlar:

http://msdn.microsoft.com/en-us/library/kxybs02x%28v=vs.80%29.aspx

Bir başına fonksiyonu bir şekilde manuel olarak satır içi uygulaması devre dışı bırakmak için bunu kullanabilir. restrict gelince


, derleyici o istediği yalnızca kullanmak serbesttir. Bu tür optimizasyonlar yapmak için derleyicileri "kandırmaya" çalışırken, aynı kodun farklı sürümleriyle uğraşmak bir şekilde kaçınılmazdır. İyi profil oluşturma uygulamaları için

+0

Bu çözüm, hem sorudaki test kodunda hem de gerçek uygulamada çalışır. Ancak, birçok kez çağrılan çok küçük bir işlevin, sınırlı sayıda kalifiye işaretçiye ihtiyaç duyması halinde, bazı durumlarda sorun olacaktır. Burada, __declspec (noinline), oldukça büyük bir çağrı yükünü zorlayacaktır. Bunun için bunu en iyi cevap olarak kabul ederek bekleyeceğim. – Boll

+0

Evet Ne demek istediğini biliyorum. Benim tahminim VS2010'da kullanılan işaretçi takma analizinin sadece işlev seviyesinde ayrıntıda olmasıdır. Dolayısıyla, bir işlevin ortasında "oluşturulmuş" olmayan hizalamayan işaretçileri ayırt edemez. Yerel olarak bildirilen işaretçiler üzerinde 'restrict' kullanılabileceğinden emin değilim. Eğer varsa, denemek için bir şey olabilir. – Mysticial

+0

Tamamen haklısınız ve şans tanımamayan yerel olarak bildirilen işaretçileri kullanmaya çalıştım."__declspec (noinline)" ifadeniz en iyi çözümdür ve mevcut durumumda (uygulamam) çalışmaktadır, bu yüzden bunu Yanıt olarak kabul ediyorum. Teşekkürler. – Boll

İlgili konular