[C++ Builder 6] pętla przywiesza program

0

Witam, napisałem w C++ Builderze 6 program, który na podstawie pewnych obliczeń generuje obrazek. Program jest napisany pod Windows tzn posiada interfejs okienkowy, który zawiera np. zegar wyświetlający sekundy na formatce.

Głównym zadaniem programu jest wykonanie pętli:

for(int x=0;x<300;x++)
{
for(int y=0; y<300; y++)
{
From1->Canvas->Pixels[x][y]= RenderujXY(x,y);
}
}

Pętla działa bardzo dobrze (tzn wynik działania programu mnie zadowala, ale niestety liczy się dosyć wolno. Nie mogę jednak zrozumieć dlaczego wywołanie pętli całkowicie zawiesza mój program, aż do jej zakończenia - tzn nawet nie można zminimalizować formatki z programem (dopiero kiedy pętla się przeliczy program wraca do normalności), natomiast do czasu zakończenia obliczeń wszystkie inne komponenty przestają działać.

Czy wie ktoś jak temu zaradzić? Jest to strasznie uciążliwe, bo np. chciałbym umieścić na formatce pasek postępu obliczeń, ale nie mogę gdyż wszystko się wiesza, i dopiero po wykonaniu obliczeń pasek postępu skacze od razu na 100%.

Pozdrawiam wszystkich

0

Roziwązanie proste:

  1. wstaw TImage na formatkę i na nim rysuj
  2. rysowanie podziel na mniejsze kawałki, które będziesz wykonywał np w zdarzeniu OnTimer (TTimer).
0

Właściwość Pixels jest bardzo powolna. Należy używać czegoś bardziej masowego: ScanLine czy Scanline o ile dobrze pamiętam.
Poza tym, jeśli RenderujXY jest bardzo czasochłonne, możnaby pomyśleć o podziale renderowania na dwa albo cztery jednoczesne wątki (każdy wątek rysuje wtedy np. co czwartą linię), aby wykorzystać procesory wielordzeniowe.
Same obliczenia, czymkolwiek one są, też zapewne dadzą się zoptymalizować (jakieś SSE...)
Po tych zmianach przyrost wydajności mógłby być może nawet 10-20 krotny.

0

Dziękuje bardzo za rady. Wstawiłem TImage na formatkę i z podzieleniem rysowania na mniejsze kawałki też sobie poradzę. Natomiast czy ScanLine nadaje się do rysowania w oknie programu? Nie upieram się żeby używać klasy Canvas i Pixels, ale czy scanline nie jest przypadkiem użyteczne tylko wtedy gdybym chciał zapisać wynik do pliku?

Tak naprawdę RenderujXY jest bardzo wolne i pochłania główną część pracy programu
Bardzo bym chętnie podzielił program na wątki (mam procesor dwurdzeniowy), ale nie mam pojęcia jak to zrobić. Czy podzielenie programu na 2 wątki jest łatwe do wykonania? Można prosić o jakieś źródło gdzie mógłbym o tym przeczytać?

Obliczenia to Ray Tracing, którego używam do symulacji pewnych zjawisk optycznych (jest to strasznie wolne, ale niestety rendering się mniej nadaje, a poza tym Ray Tracing łatwiej napisać). Bardzo bym chętnie go zoptymalizował, ale poza podzieleniem sceny na kawałki i dodaniem brył otaczających to nie mam pomysłu jak to zrobić.

0

program się blokuje, bo główny wątek, który w wolnych chwilach obsługuje kolejkę komunikatów, jest akurat bardzo zajęty. zrób obliczanie/rysowanie w osobnym wątku. i koniecznie na scanline.

0

Chciałem się Wam pochwalić, że znalazłem banalne rozwiązanie mojego problemu.

Wszyscy co do jednej osoby mi mówiły cały czas to samo co Wy - że muszę napisać obliczenia w osobnym wątku, a rozwiązanie jest dziecinnie proste. Wystarczy w każdym przebiegu pętli wywołać Application->ProcesMasseges();

Czyli następująca pętla:

for(int x=0;x<rozdzielczoscX;x++)
{
for(int y=0; rozdzielczoscY<r; y++)
{
f1->obr->Canvas->Pixels[x][y]= RenderujXY(x,y);
}
Application->ProcessMessages();
}

Działa tak samo (albo prawie tak samo) szybko jak pętla bez Application->ProcessMessages(); ale dopisanie tej linii powoduje, że wszystko chodzi przepięknie.

Pozdrawiam, tego posta napisałem gdyby ktoś kiedyś miał podobny problem.

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