test RAM'u

0

Witam, muszę napisać program odczytujący prędkość zapisu pamięci RAM. Napisałem takie oto cudo, wg mnie powinno smigac i wyswietlac poprawne dane. Jednak tak nie jest, porównywałem z everestem, gdzie średnio predkosc zapisu w moim programie bylo 2 razy mniejsza niz w everescie. Mogłby mnie ktoś uswiadomic co robie zle? Z góry dzieki :)

#include <cstdlib>
#include <iostream>
#include <time.h>
#include <math.h>
#include <iomanip>
#include <windows.h>

using namespace std;

int main(){
    double *tab,c=0,x=0,s;
    long int i;
    clock_t start, stop;
    
    
    tab=(double*)malloc(sizeof(double)*67108864);
    
    start=clock();
    //start=GetTickCount();
    for(i=0;i<67108864;i++){                                             
          tab[i]=i;                               //131072*8=1MB  4194304*8=32MB   8388608*8=64MB   
          c=c+sizeof(tab[i]);                     //16777216*8=128MB  67108864*8=512M  134217728*8=1GB
          }
    stop=clock();
    //stop=GetTickCount();
    free(tab);

    x=((double) (stop - start)) /CLOCKS_PER_SEC;
    cout<<"czas pomiaru: "<<fixed<<setprecision(3)<<x<<" sek."<<endl;
    cout<<endl; 
    cout<<"przerzucono:  "<<setprecision(0)<<c/1024<<" KB\t\t"<<c/1024/1024<<" MB"<<endl; 
    s=c/x;
    cout<<"z predkoscia: "<<setprecision(2)<<s/1024<<" KB/s\t"<<s/1024/1024<<" MB/s"<<endl;
    
    getchar();
}
0

c=c+sizeof(tab[i]);
a to po co ? Przecież znasz rozmiar danych. Poza tym test testowi nie równy.

0

wziales pod uwage fakt istnienia mechanizmu wirtualnej przestrzeni adresowej i pamieci wirtualnej? alokujesz 60mb, to juz sie moze pisac pod pamiec wirtualna..

poszukaj w dokumentacji API systemowego funkcji ktore pozwalaja Ci zarezerwowac i zaalokowac blok FIZYCZNEJ pamieci RAM i wtedy przeprowadz swoje testy

0
quetzalcoatl napisał(a)

wziales pod uwage fakt istnienia mechanizmu wirtualnej przestrzeni adresowej i pamieci wirtualnej? alokujesz 60mb, to juz sie moze pisac pod pamiec wirtualna..

poszukaj w dokumentacji API systemowego funkcji ktore pozwalaja Ci zarezerwowac i zaalokowac blok FIZYCZNEJ pamieci RAM i wtedy przeprowadz swoje testy
Nie o to mogło chodzić autorowi. Jak pisałem, test testowi nie równy. Ku ścisłości kace - tak jak napisałeś możesz testować szybkość sterty (ang. heap).

0

poza tym całą operacje zapisu do pamięci powinieneś napisać w asemblerze (rep stosd bodajże), bo to co tutaj robisz to masa operacji innych niż fizyczna operacja zapisu do tablicy,a to właśnie powoduje gorszą wydajność.

@quetzacoatl: szansa, że świeżo zaalokowana pamięć znajdzie się chociaż częściowo w pliku wymiany przy rozmiarze tablicy (zgaduję) mniejszym niż kilkanaście procent RAM jest żadna. i czy to 4B, czy 64MB, cały czas jest to pamięć wirtualna, co tutaj nie ma najmniejszego znaczenia.

0

Istnieją odpowiednie flagi alokacji, w rodzaju NOCACHE dające pewność - jeżeli prawdopodobieństwo jest niezerowe to w odpowiednio długim czasie takie zdarzenie jest pewne - zakładając obecność drugiego obciążającego system wątku już problem by mógł być. rep stosd? To idzie przez cache procesora, amortyzacja operacji na pamięci przez cache ma się nijak do szybkości zapisu, bezpośredni zapis do RAMu dają instrukcje movnt*. Kolejna sprawa - o przełączaniu zadań to słyszeliście? Jaki burdel to z cachem robi przy Waszych poprzednich koncepcjach? Ile dodatkowych danych jest przenoszonych z cache'u do RAMu i z powrotem? Użycie double to w ogóle poraźka - nie wiesz w jaki sposób kompilator rozwiąże przenoszenie... Do tego dochodzą procesory wielordzeniowe, kwestia magistral... z rozwiązań możliwych do zrealizowania dla cywila pozostaje wspomniane przenoszenie z NT w oddzielnym wątku o priorytecie rzeczywistym, wcale do tego tablic nie potrzeba. Oczywiście nie będzie to czas zapisu do RAMu, do tego mocno niedokładny, a czas zapisu przez procesor do RAMu - są to dwie różne sprawy. To tylko takie rozwinięcie Waszych koncepcji, nie sugerujcie się tym za bardzo.

0

powiedz mi, jak chcesz z cache L1 64kB, L2 512kB i nawet L3 4MB efektywnie zbuforować ZAPIS kilkudziesięciu/kilkuset MB pamięci? jeśli już, to kosmicznie spowalnia, nie do końca rozumiem czemu: http://osdir.com/ml/freebsd.performance/2006-12/msg00012.html
co do przełączania zadań - ustawiasz priorytet na czas "rzeczywisty" i tyle. przełączanie kontekstu na standardowo skonfigurowanym windows NT, nie obciążonym tysiącem wątków, zajmuje << 1% czasu procesora. oczywiście zawsze może się trafić ekstremalny komp, gdzie narzut multitaskingu zajmie dużo więcej, ale cóż, nie da się zabezpieczyć przed wszystkim.

0

mnie tam po porstu nie wdajac sie juz w bardzo niskopoziomowe szczegoly, powalilo uzycie malloca jako 'dostepu do ramu' :)

0

Dzieki wszystkim za odpowiedzi :)

ten od seksownych napisał(a)

bezpośredni zapis do RAMu dają instrukcje movnt*.

szukałem czegoś w tym kierunku i niestety nic konkretnego nie udało mi sie znaleźć. Czy mógłbys mnie jakos nakierowac?
A i jeszcze jedno, czy istnieje możliwość wyłaczenia pamięci wirtualnej w c++?

Cos czuje ze ten problem mnie przerasta ;/

0

Pamięci wirtualnej wyłączyć nie możesz - poczytaj co to tryb chroniony ze stronnicowaniem, tego właśnie Windows, BSD czy tam inny Linux używa. O instrukcjach z rodziny nt poczytasz zaś w Intel Software Developer's Manual 2B jak mnie pamięć nie myli. To taki mov dostępny bodaj od Pentiuma III, który pomija zapis do cache'u, od razu wrzuca w RAM z pominięciem cache'u, w przeciwieństwie do 'normalnego', który tylko cache uaktualnia (kiedy stare dane 'wypadają' z cache'u - wtedy są fizycznie w RAMie uaktualniane).

@ŁF, nie wiem co masz na myśli pisząc o cache'u, na początku wspomniałem o stronnicowaniu, potem odniesłem się do cache'u procesora. Pisałem, że tablica jest zbędna - w przypadku nt równie dobrze można cały czas zapisywać ten sam kawałek RAMu, cache danych w tym wypadku wiele do gadania nie ma. O wątku realtime pisałem, przy braku albo niewielkim przełączaniu zadań cache kodu problemu nie stanowi. Co nie zmienia faktu, że wynik będzie mocno niedokładny zawsze.

Hm, 4x movnt w pętli powinno starczyć, kwestia wyrównać adresy żeby jak najmniej procesor obciążać, w oddzielnym wątku realtime.

0
kace napisał(a)

A i jeszcze jedno, czy istnieje możliwość wyłaczenia pamięci wirtualnej w c++?

nie masz takiej możliwości, jesli program działa pod kontrolą jakiegokolwiek systemu operacyjnego działającego w trybie chronionym (windows, linux/unix, mac os itp), chyba, że napiszesz coś działającego w ring0, wtedy robisz co chcesz.

@T.o.s. - racja, inaczej zrozumiałem to co napisałeś wcześniej.

0

Wyniki moich poszukiwań to dodanie do kodu wstawki asemblera (w asemblerze jestem kompletnie zielony, wiec nie wiem czy to zrobilem dobrze, aczkolwiek kompilator sie nie pluje), a mianowicie prezentuje się ona tak:

     asm(
     "cr0.pg=0 \n"
     "cr0.cd=1 \n"     
        );

cr0.cd ustawione na 1 wyłacza pamięc cache a cr0.pg na 0 wyłacza stronnicowanie. Oczywiscie nie zmienia to wyników programu bo <ort>na razie </ort>nie moge znaleźć sposobu na dostanie sie bezposrednio do pamieci. Na dzisjaj koncze ale sie nie poddaje :)

0

Takie rzeczy to Ty sobie możesz robić w swoim systemie operacyjnym, w innych nawet w sterownikach skończy się to wyłożeniem systemu jeżeli nie zrobisz jeszcze masy innych rzeczy, których formalnie nie powinieneś być w stanie zrobić. W trybie użytkownika jest to niewykonalne - mov z rejestrów kontrolnych jest specjalną, uprzywilejowaną instrukcją, po prostu poleci wyjątek. Przeczytaj wszystko jeszcze raz, stronnicowanie nie ma tutaj nic do rzeczy.

0

Możesz napisać mikro system operacyjny, który jedynie przeleci pamięć bezpośrednio odwołując się do jej komórek. Taki test będzie najbardziej miarodajny, jeśli chodzi o badanie szybkości RAM'u.

0

Czy nie tak działa memtest86 ? :> Mówię o tym programiku, ktory dodaje sie do gruba, odpala z niego komputer i testuje pamięć. To taki mikrokernel, czyli wlasciwie system operacyjny

0

tak, on wlasnie tak dziala

0

Witam ponownie, dzięki waszym wskazówka udało mi się znaleźć instrukcje movnt* i ich odpowiedniki do c++ np:

MOVNTI :  void_mm_stream_si32(int * p, int a)
MOVNTQ :  void_mm_stream_pi(__m64 * p, __m64 a)

tylko ze jeżeli np chce użyć funkcji _mm_stream_si32 (includuje oczywiście biblioteke w której sie ona znajduje czyli emmintrin.h) to w devie wywala mi błąd

`_mm_stream_si32' undeclared (first use this function) 

natomiast w visual 2005 dziala bez zarzutu. Czy wie ktoś gdzie może leżec błąd? I w jaki sposób najlepiej użyć tych funkcji w ramach mojego testu?

0

ehhh czyli jednym słowem niweczy to co do tej pory zrobiłem.... to czy w takim razie możliwe jest w ogole napisane tego testu w c++?

0
kace napisał(a)

ehhh czyli jednym słowem niweczy to co do tej pory zrobiłem.... to czy w takim razie możliwe jest w ogole napisane tego testu w c++?

to nie jest kwestia języka, tylko tego że działasz pod systemem operacyjnym

0
crayze napisał(a)
kace napisał(a)

ehhh czyli jednym słowem niweczy to co do tej pory zrobiłem.... to czy w takim razie możliwe jest w ogole napisane tego testu w c++?

to nie jest kwestia języka, tylko tego że działasz pod systemem operacyjnym

Bzdura człowieku... Wspomniane funkcje to tylko dodatki z biblioteki konkretnego kompilatora będące nakładkami na wstawki w assemblerze. Tutaj system operacyjny nie ma nic do rzeczy - operacje *nt to zwyczajne instrukcje, są dostępne pod każdym procesorem do czasu PIII. Całość załatwi wstawka w asm, jeżeli zależy Ci na przenośności między kompilatorami to oifowana na preprocesorze pod konkretny kompilator. Podsumowując - system i język nie mają praktycznie nic do rzeczy, liczy się architektura procesora.

0
klacze są seksowne napisał(a)
crayze napisał(a)
kace napisał(a)

ehhh czyli jednym słowem niweczy to co do tej pory zrobiłem.... to czy w takim razie możliwe jest w ogole napisane tego testu w c++?

to nie jest kwestia języka, tylko tego że działasz pod systemem operacyjnym

Bzdura człowieku... Wspomniane funkcje to tylko dodatki z biblioteki konkretnego kompilatora będące nakładkami na wstawki w assemblerze. Tutaj system operacyjny nie ma nic do rzeczy - operacje *nt to zwyczajne instrukcje, są dostępne pod każdym procesorem do czasu PIII. Całość załatwi wstawka w asm, jeżeli zależy Ci na przenośności między kompilatorami to oifowana na preprocesorze pod konkretny kompilator. Podsumowując - system i język nie mają praktycznie nic do rzeczy, liczy się architektura procesora.

Chłopie, nie mówię tu o tych funkcjach(wstawkach skoro tak mówisz, nawet nie znam ich), odpowiadam jedynie na pytanie: czy możliwy jest czysty test fizycznej pamięci(bo rozumiem, że o taką chodzi autorowi) pod kontrolą windowsa, z poziomu uruchamianej aplikacji.

//q: ale to juz bylo powiedziane N razy...

0
crayze napisał(a)

czy możliwy jest czysty test fizycznej pamięci(bo rozumiem, że o taką chodzi autorowi) pod kontrolą windowsa, z poziomu uruchamianej aplikacji.

Tzn. tak chodzi mi o test uruchamiany pod kontrolą windows, ale wspominałem że wyniki porównuje m.in. z everestem, a więc o taki mniej więcej test mi sie rozchodzi. Udało mi się stworzyć aplikację, której wyniki są bardzo zbliżone do tych z everesta a więc cel udało mi sie osiągnąć. Oto kod programu:

#include <stdio.h>
#include <iostream>
#include <emmintrin.h>
#include <intrin.h>
#include <time.h>
#include <iomanip>   //262144*4=1MB    4194304*4=16MB  16777216*4=64MB
using namespace std;

int main ()
{
    int i,j;
    int * p;
	float x,s,z,c;
	x=z=c=0;
	
	clock_t start,stop;
	
	for(j=0;j<100;j++){
	cout<<"Postep programu... "<<j<<"%";
	
	//Dla 64MB danych

	p=new int[4194304];

	start=clock();
	for(i=0;i<4194304;i++){
		_mm_stream_si32(p+i, 10);
		}
	stop=clock();
    delete p;

	x=x+((float) (stop - start)) /CLOCKS_PER_SEC;

	start=clock();
	for(i=0;i<4194304;i++){
	}
	stop=clock();
	z=z+((float) (stop - start)) /CLOCKS_PER_SEC;
    system("cls");
	}
	c=4194304*4;
	cout<<"Przerzucono:            "<<setprecision(0)<<c/1024<<" KB\t\t"<<c/1024/1024<<" MB"<<endl;
	c=c*100;
	s=c/(x-z);
	cout<<"ze srednia predkoscia:  "<<fixed<<setprecision(2)<<s/1024<<" KB/s\t\t"<<s/1024/1024<<" MB/s"<<endl;

	getchar();
    return 0;
}

Najpierw liczę czas wykonania pętli z wykorzystanie funkcji omijajace cache. Pozniej osobno czas wykonania takie pętli, aby po odjęciu tych czasów uzyskac czas samego wypełniania pamięci. Wszystko to wykonuje w pętli 100 razy. Inaczej nie dało się zrobić bo czasami czasy byly zbyt krótkie i zdarzało się że sama pętla wykonywała się dłużej niż petla z funkcja.

0

W powyzszym kodzie nie powinno byc czasem delete []p?

0
zielonyplot napisał(a)

W powyzszym kodzie nie powinno byc czasem delete []p?

tak tak, oczywiscie racja powinno byc delete []p

0

Ok, skoro zapis już mam za sobą to teraz przyszedł czas na sprawdzenie prędkości odczytu z pamięci. Ja zrobiłem taką o to pętle

	for(i=0;i<4194304;i++){
		*(p+i);
		}
	stop=clock();

ale czas jej wykonania jest prawie taki sam jak czas wykonania pętli bez tej instrukcji, co daje czasami nawet i ujemne wyniki przy obliczania predkości odczytu. Czy może ma ktoś jakis pomysł w jakis sposób można to sprawdzic?

0

Kompilator najwyraźniej optymalizuje operację wywalając odczytanie poza pętlę, posłuż się specyfikatorem volatile.

0

I jeszcze jedna uwaga - przypisuj odczytaną wartość do zmiennej tymczasowej - inaczej operacja odczytu może mimo wszystko zostać uznana za nadmiarową.

0

Witam ponownie,
w trakcie testów programu pojawił sie kolejny błąd, otóż jak już wiemy funkcja

_mm_stream_si32(p+i, 10);

której użyłem w programie rezerwuje nam pamięć kolejnymi elementami tablicy. I o ile pamięć zarezerwowaną dla tablicy jestem w stanie zwolnić instrukcją

delete []p;

to pamięci zarezerwowanej przez użytą funkcję zwolnić nie potrafię. I np dla duży paczek danych po kilku wykonaniach pętli po prostu brakuje pamięci i program się zawiesza. Troche już szukałem, lecz bez jakiś lepszych rezultatów wieć mam pytanie czy istnieje funkcją która by tą pamięć zwalniala?

1 użytkowników online, w tym zalogowanych: 0, gości: 1