Próbowałem użyć ograniczonych kwalifikowanych wskaźników i napotkałem problem. Poniższy program jest prosty i przedstawia tylko problem.Ograniczanie wskaźników i wstawianie
Funkcja calc_function używa trzech wskaźników, które są ograniczone, więc "SHALL" nie są aliasami. Podczas kompilowania tego kodu w visual studio funkcja będzie wstawiana, więc bez żadnego powodu program Visual Studio 2010 ignoruje kwalifikatory. Jeśli wyłączę wpisywanie, kod wykonuje więcej niż sześć razy szybciej (od 2200ms do 360ms). Ale nie chcę wyłączać wprowadzania w całym projekcie ani całego pliku (ponieważ wtedy będzie to wywoływać narzut w np. Wszystkich programach pobierających i ustawiających, co byłoby okropne).
(może być jedynym rozwiązaniem jest wyłączenie inline tylko o tej funkcji?)
Próbowałem stworzyć tymczasowy ograniczyć wykwalifikowanych wskaźniki do funkcji, zarówno na górze i na pętli wewnętrznej spróbować powiedzieć kompilator, który obiecuję, że nie ma aliasingu, ale kompilator mi nie uwierzy i nie zadziała. Próbowałem również poprawić ustawienia kompilatora, ale jedynym, który znalazłem działa, jest wyłączenie wstawiania.
Byłbym wdzięczny za pomoc w rozwiązaniu tego problemu optymalizacji.
Aby uruchomić program (w realeasemode), nie zapomnij użyć argumentów 0 1000 2000. Dlaczego użycie argumentów userinput/program ma na celu upewnienie się, że kompilator nie może wiedzieć, czy istnieje czy nie jest? t aliasowanie między wskaźnikami a, b i c.
#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 za dobre praktyki profilowania. Zdecyduję się nie narzekać na specyfikatora formatu. P.S. 'clock' zwraca' clock_t', a nie 'time_t'. – Hurkyl
Spróbuj chronić wywołanie funkcji, sprawdzając, czy przesunięcia są wystarczająco duże. Najprawdopodobniej będziesz musiał użyć prawdziwych zmiennych 'int', ale przechowaj przesunięcia, zamiast hacku, którego użyłeś. – Hurkyl
@Hurkyl Myślałem, że clock_t i time_t były zarówno typedefs do tego samego, ale masz rację. (Btw, jak mogę edytować mój post z pytaniami?) – Boll