LINUX.ORG.RU

[C++][тормоза] matrix template

 ,


0

0

Есть шаблон класса для матрицы, где двумерная матрица реализована как одномерная:

template <class T> class matrix
{
	private:
		size_t Height;
		size_t Width;
		T *Val;
	public:
		T& operator () (size_t i, size_t j)
		{
			return Val[Width*(i-1)+j-1];
		}
	........
}
Не пойму почему скорость доступа к элементам матрицы в 5 раз медленнее по сравнению с:
double *A3 = new double [n*n];
и доступом к элементу в виде:
A3[n*(i-1)+j-1]

★★★★★

1. Обработка доступа к функции. 2. Это шаблон детка! :))

Короче зафиксируй тип, просто что бы был класс и замерь скорость :) потом сделать простую функцию и тоже замерь скорость тогда и поймёшь.

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

typedef farMath::matrix<double> Matrix; - с ней работаю

Ну я бы понял если бы оно было на 20% медленнее, но не в 5 раз же :(

Zodd ★★★★★
() автор топика

Что подскажет сообщество ЛОРа при решении этой проблемы?

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

ну тогда всё ясно.
Юзай mingw,gcc4 (-O2 как минимум),
или на худой конец Intel.

Работа с шаблонами это испытание для C++ компиляторов. Если не включена оптимизация там чёрти что выходит.

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

Оказывается почти нету разницы при максимум оптимизации. Фуф, ах ипугался.

На сколько gcc лучше?

Zodd ★★★★★
() автор топика
Ответ на: комментарий от stalkerg

Еще один вопрос: Что быстрее - реализация через двумерный массив или через одномерный?

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

Я где-то читал что одномерный. Вроде-бы в сишарпе двумерные массивы реализованы через одномерные. Да и malloc'ов будет меньше.

Elverion
()
Ответ на: комментарий от Zodd

Что значит «реализация через двумерный массив»? В C++ двумерных массивов нет.(есть в Си, но и то, они статические)

Love5an
()
Ответ на: комментарий от Love5an

Вот так:

int** A = malloc(n * sizeof(int*));
for (int i = 0; i < n; i++)
    A[i] = malloc(n * sizeof(int));

n + 1 маллок.

Но это самый простой способ, можно и через один malloc сделать.

Elverion
()

Если размер матрицы - степень двойки, то выфетчивать нужный элемент можно при помощи битового сдвига и AND-а. Тип T в этом классе - ненужный мудизм: если используешь double-ы, то все равно завяжешься на них в куче других мест, так что нечего порождать сложности там где их нет. А вот размеры неплохо бы вынести в параметры шаблона, т.к они должны быть статическими чтобы компилятор мог двойные циклы разворачивать.

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

Если есть структура данных, к которой можно обращатся так:

int i = A[1][2]

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

Elverion
()
Ответ на: комментарий от Zodd

быстрее с одномерным.

а как удобнее зависит от программиста и задачи. Иногда фортрановский стиль удобно использовать. Когда элементы хранятся по столбцам, т.е. 1 2 3 4 => (1,3,2,4)

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

Работа с шаблонами это испытание для C++ компиляторов. Если не включена оптимизация там чёрти что выходит.

Э-э-э, пруф?

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

Никогда не понимал эту терминологию. Если С++ что-то досталось от Си, то значит в С++ этого нет? Бред какой-то. И почему статические? Больше подходит константной размерности.

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

>Никогда не понимал эту терминологию. Если С++ что-то досталось от Си, то значит в С++ этого нет?
Это не фича С++, это фича Си. Примерно так же, как указатели - не фича Common Lisp, однако дергаются через FFI.

И почему статические? Больше подходит константной размерности.

Это элементарная общепринятая терминология, вообще-то.
google://статические массивы
кроме того:
google://динамические массивы

Love5an
()
Ответ на: комментарий от Love5an

Это всё понятно и всё это конечно не новость. Только говорить, что в С++ нет массивов очень странно, надо говорить, что в С++ есть Си массивы. К тому же разделять фичи в С++ на С++ и Си тоже не совсем корректно. И термин статический или динамический, больше подходит не к размеру, а к способу создания. Так как интерпретировать размер можно по разному.

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

>К тому же разделять фичи в С++ на С++ и Си тоже не совсем корректно.
Это как раз более чем корректно. Т.к. мешать их нельзя в подавляющем большинстве случаев.

И термин статический или динамический, больше подходит не к размеру, а к способу создания.


А термин жопа больше подходит не к жопе, а к стране, в которой мы живем, и что?
В Си для адресации элемента в двумерном(и вообще *-мерном, тем более) массиве через встроенные средства языка(т.е. не подсчет оффсета по row-major ручками) надо чтобы компилятор знал размерности(конкретно для матриц - количество столбцов) массива статически. Многомерные массивы там вообще статические с какой стороны не посмотри - их даже аллоцировать нельзя в рантайме(можно только одномерные, напомню), не то что менять их размерности(В C++ даже у одномерных массивов менять размерность нельзя - renew то никакого нету ведь. Ну разве что есть уродский std::vector, но это не считается).

Love5an
()
Ответ на: комментарий от Love5an

>Т.к. мешать их нельзя в подавляющем большинстве случаев.
Что нельзя мешать? Это разделение искуственно.

В Си для адресации элемента в двумерном(и вообще *-мерном, тем более) массиве через встроенные средства языка(т.е. не подсчет оффсета по row-major ручками) надо чтобы компилятор знал размерности(конкретно для матриц - количество столбцов) массива статически.


Причём здесь жопа? Мы говорим об одном том же, лекция была совершенно не к чему. Статические имеют константный размер.


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

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

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

Ну и нахрен мне это? Массив от этого статическим перестал быть?
Вот когда вместо 10 можно будет n, да еще и изменять размер потом, тогда и можно будет о чем-то говорить.

Love5an
()
Ответ на: комментарий от stalkerg

Ну ты отжег так отжег. В данном конкретном случае, что шаблон, что не шаблон абсолютно никак не влияет на производительность.

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

Только надо решить для себя, как будет в дальнейшем производиться доступ - по столбцам или по строкам. Если элементы размещаются строками, а обходить столбец, то производиельность может заметно просесть. От трети до пяти раз, в зависимости от архитетуры и размера кеша.

anonymous
()

inline тебе в помощь. Сильно рассчитывать на оптимизатор не советую. Когда код попадает в шаловливые ручки оптимизатора понять что там на выходе будет очень трудно.

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

Почему именно использую шаблон - есть матрицы int, double - пытался избежать повтора кода.

выфетчивать нужный элемент можно при помощи битового сдвига и AND-а.

Не совсем понимаю как это сделать. Можно подробней.

Zodd ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> Если элементы размещаются строками, а обходить столбец, то производиельность может заметно просесть.

Везде использую по строкам, т.к. это гораздо нагляднее

//раньше работал в фортране

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Miguel

> > Работа с шаблонами это испытание для C++ компиляторов. Если не включена оптимизация там чёрти что выходит.

Э-э-э, пруф?

Перечитай тред. Шаблонная реализация в 5-раз медленее (надеюсь, ты прочитаешь первые два предложения в этом посте, прежде чем отвечать).

anonymous
()
Ответ на: комментарий от Zodd

>В шаблонах использовать inline не есть гуд.

Мне не понятно, обоснуй почему inline в шаблонах это плохо.

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

>Перечитай тред. Шаблонная реализация в 5-раз медленее...

Ну и что ты там померил? Сферический код в вакууме. Почему ты решил что дело в шаблонах? На таких примерах измеренная производительность легко может «сорваться» из-за «какой-нибудь мелочи».

pathfinder ★★★★
()

возвращай Val и работай с ним напрямую, очевидно же, что при вызове метода происходят дополнительные действия и шаблон тут не причем

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

>Перечитай тред. Шаблонная реализация в 5-раз медленее (надеюсь, ты прочитаешь первые два предложения в этом посте, прежде чем отвечать).

Ну а чисто логически подумать? Шаблонный код развернется в точно такой же, как и не шаблонный с точностью до name mangling

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

Почему ты решил, что дело не в них?

Гребаный демагог. Поясню. В примере с шаблонами потери производительности должны выйти из-за накладных расходов на вызов функции, в примере с простым массивом весь код делается по извлечению числа из массива делается «inline». По мимо отсутствия вызова функции во втором случае есть большие просторы для оптимизации вот пример:

Пример

template <class T>
class Matrix
{
	int n;
	T* array;
	inline Matrix(int _n)
	{
		n=_n;
		array = (T*) malloc(sizeof(T)*n*n);
	}
	inline ~Matrix()
	{
		free(array);
	}

    inline float Get(int i,int j)
	{
		return array[n*(i-1)+(j-1)];
	}
};

А теперь используем этот шаблон при включенной оптимизации:

int main()
{
  Matrix<float> m(5);

  float d1 = m.Get(2,2);
  printf("get() %f\n",d1);
  return 0;
}

Вопрос: сколько инструкций процессора будет использовано для исполнения m.Get(2,2) ?

У меня ноль интсрукций.

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

> Перечитай тред. Шаблонная реализация в 5-раз медленее (надеюсь, ты прочитаешь первые два предложения в этом посте, прежде чем отвечать).

так шаблоны то тут не при чем. Виноват вызов функции, неважно шаблонный он или нет. Оптимизация была отключена, inline не работал.

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

>У меня ноль интсрукций.

А если в другом случае на эту инструкцию потребуется 1 и более комманд процессора, то буду говорить что шаблоны работают быстрее в бесконечное(sic!) число раз.

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

> inline float Get(int i,int j)

любое определение (не декларация) метода класса непосредственно внутри определения класса автоматически означает употребление ключевого слова inline.

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

Гм. Медленнее чего? Я вижу две реализации, одна - через темплейт, другая - через int[]. Реализацию через класс (без темплейта) я не вижу.

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

>Ну разве что есть уродский std::vector, но это не считается).

Один чел в форуме std::valarray + std::gslice хвалил. Типа оно почти как Фортран.

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