_pv 78 6 февраля, 2019 Опубликовано 6 февраля, 2019 · Жалоба 34 minutes ago, k155la3 said: Это получится, насколько понял, Protothreads http://dunkels.com/adam/pt/ ? ну не совсем, там в макросах прячется условный goto, чтобы внутрь бесконечного цикла в нужное место при очередном вызове сразу запрыгивать, делая вид что просто продолжили с того места откуда в прошлый раз return был, тут же надо просто один и тот же кусок кода оформленный в "локальную" функцию несколько раз позвать, но да, похоже наверное. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба Во-первых, огромное спасибо всем за интересные советы! Лямбды (вложенные функции) раскрывать в goto - не реально, они как раз параллелятся, по ним часто мультитред делается, то есть их выполнение зависит от числа ядер или тредов. Идея с отдельным классом для многомерных массивов понравилась, только я ее доработал, чтоб производительность не падала. Получилось так: #include <math.h> template <typename T> class MDA2 { public: T *A; int LDA; MDA2() {}; MDA2(T *aA, int aLDA) { A=aA; LDA=aLDA; }; void Init(T *aA, int aLDA) { A=aA; LDA=aLDA; return; }; T &operator()(int i1, int i2) { return A[i2+LDA*i1]; }; T *operator()(int i1) { return A+LDA*i1; }; }; void Func3(int N, int M, double *_X) { MDA2<double> X(_X, N); auto Test = [&] () -> void { int i, j; for(i=0; i<N; i++) for(j=0; j<M; j++) X(i,j)=(double)(i*1000+j); }; int i, j; Test(); for(i=0; i<N; i++) { double s=0; for(j=0; j<M; j++) s+=X(i,j)*X(i,j); s=(s>0.)?1./sqrt(s):0.; for(j=0; j<M; j++) X(i,j)*=s; } return; } Конечно надобно на все размерности 2,3,4,... написать такие темплейты, но по крайней мере 1. пример компилится на всех адекватных и свежих компилерах включая интел, гну и вижуал 2. после пробного перетаскивания пары сотен своих функций на такой стиль написания падения производительности работы программы не было замечено. Из пожеланий хочется как-то сказать компилятору, что LDA внутри класса не меняется, и компилер вправе оптимизировать конструкции X(i,j) с постоянным i внутри цикла, но пока не придумал как. GNU сам в большей части такое делает, но хочется компилеру "навязать" свое мнение, чтоб наверняка. То есть, ИМХО, более-менее решение найдено, спасибо всем большое за интересные обсуждения! PS: Если кто заметит/увидит что как можно еще упростить-улучшить, поделитесь, пожалуйста, идеями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 4 minutes ago, iiv said: Из пожеланий хочется как-то сказать компилятору, что LDA внутри класса не меняется, template <typename T> class MDA2 { public: T *A; const int LDA; MDA2(T *aA, int aLDA) : LDA(aLDA) { A=aA; }; T &operator()(int i1, int i2) { return A[i2+LDA*i1]; }; T *operator()(int i1) { return A+LDA*i1; }; }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 14 minutes ago, xvr said: template <typename T> class MDA2 { public: T *A; const int LDA; MDA2(T *aA, int aLDA) : LDA(aLDA) { A=aA; }; T &operator()(int i1, int i2) { return A[i2+LDA*i1]; }; T *operator()(int i1) { return A+LDA*i1; }; }; Супер, спасибо большое!!! А как еще сказать, что указатель (*A) - тоже константа, но сделать так, что *A конечно можно было бы менять? По аналогии попробовал, но не получилось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 35 минут назад, iiv сказал: Идея с отдельным классом для многомерных массивов понравилась, только я ее доработал, чтоб производительность не падала. Я не думаю, что при нормальном уровне оптимизации такое решение будет работать быстрее, чем моё. К тому же, я исходил из предположения, что адресацию массивов квадратными скобочками желательно оставить:) В любом случае, рад, что идея помогла. 18 минут назад, iiv сказал: А как еще сказать, что указатель (*A) - тоже константа, но сделать так, что *A конечно можно было бы менять? По аналогии попробовал, но не получилось. T *const A; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 46 минут назад, iiv сказал: Идея с отдельным классом для многомерных массивов понравилась, только я ее доработал, чтоб производительность не падала. Зачем? В бусте же есть, вполне нормальная реализация. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба Кстати, вспомнил. В gsl есть multi_span. По идее, это должно идеально подойти. (не смотрите, что это микрософт, это должно работать в любом современном компиляторе) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nixon 4 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 2 часа назад, iiv сказал: Из пожеланий хочется как-то сказать компилятору, что LDA внутри класса не меняется, и компилер вправе оптимизировать конструкции X(i,j) с постоянным i внутри цикла, но пока не придумал как. GNU сам в большей части такое делает, но хочется компилеру "навязать" свое мнение, чтоб наверняка. template <typename T, int aLDA> class MDA2 { enum : int { LDA = aLDA }; public: T *A; MDA2(T *aA) : { A=aA; }; T &operator()(int i1, int i2) { return A[i2+LDA*i1]; }; T *operator()(int i1) { return A+LDA*i1; }; }; Если вы конечно не используете экземпляр класса повторно с переинициализацией LDA Чой то я, там enum вообще не нужен - используйте параметр шаблона напрямую Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 23 minutes ago, Nixon said: Если вы конечно не используете экземпляр класса повторно с переинициализацией LDA не, похоже так не получится, компилер ругается, что error: ‘N’ is not a constant expression { MDA2<double, N> X(_X); на момент инициализации - это как-то вычисленная переменная или входной аргумент в функции, а вот потом - действительно константа. 2 hours ago, AHTOXA said: Я не думаю, что при нормальном уровне оптимизации такое решение будет работать быстрее, чем моё. К тому же, я исходил из предположения, что адресацию массивов квадратными скобочками желательно оставить:) В любом случае, рад, что идея помогла. Мне Ваша идея реально очень нравится, и видится более разумной, чем модификация х[i][j][k] -> (i,j,k) но компилятор-то тупой. У меня часто возникает конструкция for(j=0; j<M; j++) ... X[i][j][k] ... или на больших размерностях. Идеологически да, Ваша версия должна пересчитываться внутри цикла на то, что заводится новый указатель XX = X + k + N*M*i; и обращение выполняется как XX[j*N] но по-видимому GNU тупит и не может эту конструкцию увидеть. На моем классе он таки делает то, что надобно. На других компилерах не пробовал, только проверил, что все стандартно компилится. 2 hours ago, AHTOXA said: T *const A; Спасибо большое!!! Я С++ знаю только на уровне еще очень старого стандарта 2.0 (89 год кажется) и с тех пор только на фортране и С программировал и в новых стандартах пока подтормаживаю, спасибо большое, что на путь истинный наставили! 2 hours ago, Kabdim said: Зачем? В бусте же есть, вполне нормальная реализация. буст пока не пользовали, так как код был на С, а не С++. В эту сторону тоже будем смотреть, но очень осторожно. Много раз наблюдал и слышал от других, что перекомпиляция С кода на С++бывает, что существенно ухудшает производительность программы. 51 minutes ago, AHTOXA said: Кстати, вспомнил. В gsl есть multi_span. По идее, это должно идеально подойти. Спасибо! Читаю, разбираюсь. Спасибо большое!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба Позвольте, пожалуйста, еще вопрос в тему, чтоб и рыбку съесть и ... Хочу компиллеру объяснить, что все внутренности класса константы, но иногда таки нет :) #include <math.h> template <typename T> class MDA2 { public: const int LDA; T *const A; MDA2(T *aA, int aLDA) : LDA(aLDA), A(aA) {}; T &operator()(int i1, int i2) { return A[i2+LDA*i1]; }; T *operator()(int i1) { return A+LDA*i1; }; }; void Func3(int N, int M, double *_X) { MDA2<double> X(_X, N); auto Test = [&] () -> void { int i, j; for(i=0; i<N; i++) for(j=0; j<M; j++) X(i,j)=(double)(i*1000+j); }; int i, j; Test(); for(i=0; i<N; i++) { double s=0; for(j=0; j<M; j++) s+=X(i,j)*X(i,j); s=(s>0.)?1./sqrt(s):0.; for(j=0; j<M; j++) X(i,j)*=s; } // то есть до этого места все внутренности этого класса постоянны, и компилер может все отоптимизировать, &X=MDA2<double>(_X+5, N*2); // а вот тут я хочу и адрес новый присвоить, и размерность поменять, но из-за // отсутствия опыта написания таких извращений не могу побкедить синтаксис, посоветуйте, пожалуйста, как это сделать! for(i=0; i<N; i++) { double s=0; for(j=0; j<M; j++) s+=X(i,j)*X(i,j); s=(s>0.)?1./sqrt(s):0.; for(j=0; j<M; j++) X(i,j)*=s; } return; } Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 1 час назад, iiv сказал: void Func3(int N, int M, double *_X) { MDA2<double> X(_X, N); Спасибо! здесь указывать <double> необязательно, компилятор сам выведет тип: MDA2 X(_X, N): 1 час назад, iiv сказал: // то есть до этого места все внутренности этого класса постоянны, и компилер может все отоптимизировать, &X=MDA2<double>(_X+5, N*2); // а вот тут я хочу и адрес новый присвоить, и размерность поменять, но из-за // отсутствия опыта написания таких извращений не могу побкедить синтаксис, посоветуйте, пожалуйста, как это сделать! Никаких извращений не надо. Либо вы просто присваиваете переменной X новое значение: X = MDA2(...); либо заводите другую переменную: MDA X2(..); и работаете с ней. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба Огромное спасибо, AHTOXA за постые и понятные советы!!! Действительно <double> с 17 стандарта вроде бы и не нужен, спасибо!!! А вот с присвоением - так и не понял можно ли или нет... #include <math.h> template <typename T> struct MDA2 { const int LDA; // да, я понимаю, что можно убрать отсюда const и тогда то, что внизу будет работать, T *const A; // но хочется как-то предупредить компилер, что между такой инициализацией A и LDA не меняются MDA2(T *aA, int aLDA) : LDA(aLDA), A(aA) {}; T &operator()(int i1, int i2) { return A[i2+LDA*i1]; }; T *operator()(int i1) { return A+LDA*i1; }; }; void Func3(int N, int M, double *_X) { MDA2 X(_X, N); auto Test = [&] () -> void { int i, j; for(i=0; i<N; i++) for(j=0; j<M; j++) X(i,j)=(double)(i*1000+j); }; int i, j; Test(); for(i=0; i<N; i++) { double s=0; for(j=0; j<M; j++) s+=X(i,j)*X(i,j); s=(s>0.)?1./sqrt(s):0.; for(j=0; j<M; j++) X(i,j)*=s; } X=MDA2(_X+5, N*2); for(i=0; i<N; i++) { double s=0; for(j=0; j<M; j++) s+=X(i,j)*X(i,j); s=(s>0.)?1./sqrt(s):0.; for(j=0; j<M; j++) X(i,j)*=s; } return; } Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба А, ну да, точно. Там же константные члены, оператор присваивания не сработает. Ну тогда создайте новую переменную: MDA2 X2(_X+5, N*2); и не забивайте себе голову:) Это как раз и позволит сказать компилятору, что в цикле можно оптимизировать по полной, после цикла передвинуть эти константы в другое положение, и затем снова оптимизировать по полной. Причём сказать это полностью прозрачно, понятно для компилятора, понятно для человека, читающего этот код, без всяких хаков и ухищрений:) Добавлю, что если обращений к первой переменной больше не будет, то компилятор создаст вторую прямо на месте первой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iiv 29 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба Точно, спасибо огромное!!! Я еще не до конца подсекаю концепцию С++ и часто делаю по С-шному, а Вы так классно и понятно объяснили!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 7 февраля, 2019 Опубликовано 7 февраля, 2019 · Жалоба 15 минут назад, iiv сказал: Я еще не до конца подсекаю концепцию С++... Я вот вообще не понял, что происходит в этой теме Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться