LINUX.ORG.RU

[C] Странное поведение двойного указателя

 


0

0

Уже второй час не могу понять, что не так в функции.

float **image - двумерный массив (изображение), float *ptr - временный указатель. Если я пишу

		for(j=0; j<YHb; j++){
                        ...
			ptr = &image[j][1];
			...
то все работает замечательно. Но мне нужно пропустить первую строку изображения. И я пишу
		for(j=1; j<YHb; j++){
			...
			ptr = &image[j][1];
                        ...
При этом ptr указывает непонятно куда (все значения пикселей получаются равными 0.0), и вычисление выполняется раз в 20 дольше.

Перепробовал и отключать оптимизацию при компиляции, и -O1 - все равно программа ведет себя так странно. В чем может быть проблема?

☆☆☆☆☆
Ответ на: комментарий от Eddy_Em

Не умею я им пользоваться.

gdb --args ./myprogram arguments # или gdb ./myprogram, если аргументов не надо
(gdb) b findminmax
(gdb) r
n -- step over
t -- strace into
c -- continue
p ARG -- print

Ничего сложного, зато ответит на многие твои вопросы. Смотри info gdb и осваивай. Главное не забудь -O0 -fno-inline -g при компиляции.

Если это кажется ну ааафигеть каким сложным, всегда можно навтыкать отладочной печати.

linuxfan
()

O_o

Ничего не понимаю, но вот так заработало:

	inline void findminmax(float **image, char flag){
		int w2 = GRAB_WIDTH/2-1, h2 = GRAB_HEIGHT/2-1, s2 = wImageSize/2;
		int XLb = w2, XHb = s2+w2, YLb = h2, YHb = s2+h2;
		int i, j, px, py;
		float *ptr, pixval;
		if(flag){
			min_ = 1e30; max_ = -1e30;
			for(i=0; i<2; i++) for(j=0; j<2; j++){
				QMax[i][j] = -1e30; QMin[i][j] = 1e30;
				Areas[i][j] = 0.;
			}
		}
		for(j=1; j<YHb; j++){
			if(j < YLb) py = 1;
			else if(j > s2) py = 0;
			else continue;
			ptr = *(image++) + 1;
			for(i=1; i<XHb; i++, ptr++){
				if(i < XLb) px = 0;
				else if(i > s2) px = 1;
				else continue;
				pixval = *ptr;
				if(min_ > pixval) min_ = pixval;
				else if(max_ < pixval) max_ = pixval;
				if(QMin[py][px] > pixval) QMin[py][px] = pixval;
				else if(QMax[py][px] < pixval) QMax[py][px] = pixval;
				Areas[py][px] += fabs(pixval);
			}
		}
	}

Теперь буду проверять, как быстрее считать - через указатели на указатели, или линейным массивом.

Eddy_Em ☆☆☆☆☆
() автор топика

Опять я на пустом месте придумал проблему. Я работаю с вейвлет-образом расширенного до 1024х1024 изображения. Начало координат у изображения - в левом верхнем углу, а в дурацком openGL - в левом нижнем. В итоге я вычислял ширины гистограмм в пустых областях.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Reset

Для теста полностью избавился от двойных указателей. Получились следующие результаты: с двойным указателем вычисление вейвлет-образа первого уровня для изображения 1024х1024 занимает 40мс при -O6 и 80мс при -O0. С одинарным указателем -O6 дает 150мс, а -O0 - 180мс.

Так что все-таки использование двойных массивов существенно быстрее вычисления адресов в одинарных массивах.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

Ну что я могу сказать, жопа конечно. Вот тестик

http://pastebin.com/dXk37jZ8

на q9550 результат такой

$ ./a.out 
write
A* rand 1.774473
A* i,j  2.977252
A* j,i  14.628651
B**rand 1.788096
B**i,j  2.966986
B**j,i  4.373903
read
A* rand 1.215256 50302576.908659
A* i,j  0.117169 208866794.499816
A* j,i  0.116308 208866794.499816
B**rand 1.215297 49485621.955180
B**i,j  0.116261 208866794.499816
B**j,i  0.107461 208866794.499267

** быстрее на запись, на чтение разницы нет

Reset ★★★★★
()
Ответ на: комментарий от Eddy_Em

Такое возможно, смотрим мой тест. Дело тут не в вычислении индекса, тут идет неоптимальная работа с кешем. Вообще печально это, современное железо работает не так как описано в древних книгах.

У меня есть еще более печальный тест в котором умножается матрица на вектор http://pastebin.com/Hu1ECz8D

результат на q9550:

$ ./a.out 
clever:
1 24.352339
2 17.203179
4 18.433826
stupid:
1 24.280233
2 16.680339
4 17.871868
clever2:
1 24.204253
2 17.553917
4 18.842095
stupid2:
1 21.425853
2 16.164754
4 18.225076
Левая колонка - число потоков. clever это древний классический алгоритм блочного умножения, человек от которого я о нем узнал утверждает, что на древних xeon'ах этот алгоритм давал линейный прирост при увеличении ядер, stupid это алгоритм влоб, который прироста в общем случае давать не должен. суффикс 2 означает, что работаем с **

Так вот, никакой из алгоритмов не дает прироста при переходе 2->4, а при переходе 1->2 прирост не такой какой ожидаем. Я уже затрахался искать причину этого феномена и не знаю как сделать, чтобы было всё за2.71бись.

Reset ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.