Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > switch в compile-time


Автор: W4FhLF 12.10.2010, 11:04
Не знаю как тему назвать.

У меня есть два параметра. Для заданного диапазона значений этих параметров нужно сгенерировать процедуры в compile-time! Сразу скажу, что прога работает на GPU, поэтому цель вынести как можно больше вычислений в compile-time (чтобы компилятор мог развернуть циклы), размер полученного объектника не имеет никакого значения. 

Имеет смысл заюзать шаблоны. Самая "тупая" реализация, которая написана на первое время выглядит так:

Код

    switch(CSize * RSize)
    {
        case 81:
            processingKernelTex<9, 9>(d_Dst, columns, rows);
            break;
        case 99:
            processingKernelTex<11, 9>(d_Dst, columns, rows);
            break;
        case 169:
            processingKernelTex<13, 13>(d_Dst, columns, rows);
            break;
        case 285:
            processingKernelTex<19, 15>(d_Dst, columns, rows);
            break;
    }


Очевидно, что она не подходит хотя бы потому что произведение коммутативная операция. Т.е. для пары параметров 11, 9:
11 * 9 = 99 = 9 * 11 = 99. А вычисления для (11, 9) и (9, 11) должны быть разные!

Я знаю диапазоны изменения эти параметров и хочу для каждой пары сгенерировать свою реализацию. Есть идеи? 

Автор: azesmcar 12.10.2010, 11:12
W4FhLF

А сами параметры известны в compile-time?

Автор: boostcoder 12.10.2010, 11:13
http://www.boost.org/doc/libs/1_44_0/libs/mpl/doc/refmanual/type-selection.html

Автор: W4FhLF 12.10.2010, 11:23
Цитата(azesmcar @  12.10.2010,  11:12 Найти цитируемый пост)
А сами параметры известны в compile-time?


Они передаются параметрами (CSize, RSize) в функцию. Мне лишь известно, что они меняются в диапазоне 5-25 скажем. Т.е. может быть 400 комбинаций, для switch'a многовато и к тому же поскольку параметров два нужно писать вложенный switch. 

boostcoder, boost'a под этот компилятор (NVIDIA C/C++ Compiler) нет. А залазить в MPL самому страшно  smile 

Автор: boostcoder 12.10.2010, 11:26
Цитата(W4FhLF @  12.10.2010,  11:23 Найти цитируемый пост)
boostcoder, boost'a под этот компилятор (NVIDIA C/C++ Compiler) нет. А залазить в MPL самому страшно

if_<> написать запросто smile

Добавлено через 53 секунды
Цитата(W4FhLF @  12.10.2010,  11:23 Найти цитируемый пост)
boost'a под этот компилятор (NVIDIA C/C++ Compiler) нет

кстати, пробовал?

Автор: mes 12.10.2010, 11:29
Цитата(W4FhLF @  12.10.2010,  10:04 Найти цитируемый пост)
 А вычисления для (11, 9) и (9, 11) должны быть разные!


Цитата(W4FhLF @  12.10.2010,  10:23 Найти цитируемый пост)
Мне лишь известно, что они меняются в диапазоне 5-25 скажем.

Код

switch( (c-5)*20+(r-5) )
или
array [ (c-5)*20+(r-5)] ();


Автор: djamshud 12.10.2010, 11:30
Можно сделать матрицу своих шаблонных колбеков. X и Y координаты - это соответственно значения первого и второго патаметров. К нам попадает пара значений - сразу вызываем обработчик.

Если диапазоны параметров XY не пересекаются, то можно существенно сократить матрицу, сделав X и Y соотвественно диапазонами этих параметров (т.е. 9..13, 13..19 и т.д.) - в таком случае к нам падает пара значений, находим к каким диапазонам они относятся, вызываем ячейку, им соответствующую.

У вас параметры неизвестны в компайл-тайм, так что о полноценной компайл-тайм реализации речи идти не может.

Добавлено через 2 минуты и 52 секунды
Всякие шаблонные if опять же работает только для заранее известных значений.

Автор: W4FhLF 12.10.2010, 11:33
Цитата(boostcoder @  12.10.2010,  11:26 Найти цитируемый пост)
if_<> написать запросто 


Я учту, спасибо. 

Юзать буст там не пробовал. Они в последний год только начали добавлять поддержку С++ features, но всё равно очень многое из стандарта отсутствует. 


mes, а что с этим делать?

Добавлено @ 11:37
Цитата(djamshud @  12.10.2010,  11:30 Найти цитируемый пост)
Можно сделать матрицу своих шаблонных колбеков. X и Y координаты - это соответственно значения первого и второго патаметров. К нам попадает пара значений - сразу вызываем обработчик.


А в ячейках хранить указатели на обработчики? Я к сожалению не могу вызывать функции по указателю (хотя эта возможность была добавлена в последнюю версию компилятора, но я юзаю предыдущую), но можно сделать доп. обёртку, в таком случае такой вариант подойдёт. Но мне обработчики вручную генерить? 

Цитата(djamshud @  12.10.2010,  11:30 Найти цитируемый пост)
У вас параметры неизвестны в компайл-тайм, так что о полноценной компайл-тайм реализации речи идти не может.


Да, но я не против, чтобы компилятор сгенерил все возможные варианты. smile Главное чтоб не вручную это делать. 

Автор: mes 12.10.2010, 11:38
Вам надо для всех 400 вариантов задать функцию, которая представлена шаблоном основывающимся на "координатах" CSize, RSize ?

или я неправильно понял задачу ?

Автор: W4FhLF 12.10.2010, 11:41
Цитата(mes @  12.10.2010,  11:38 Найти цитируемый пост)
Вам надо для всех 400 вариантов задать функцию, которая представлена шаблоном основывающимся на "координатах" CSize, RSize ?


Мне надо задать 400 функций для всех комбинаций параметров CSize, RSize. 

Автор: djamshud 12.10.2010, 11:42
W4FhLF, так может проще просто сгенерировать мега-свитч?

Автор: W4FhLF 12.10.2010, 11:43
djamshud, писать внешний скрипт для этого? Буду это делать в том случае, если средствами языка и препроцессора не решу. 

Автор: mes 12.10.2010, 11:54
Цитата(W4FhLF @  12.10.2010,  10:41 Найти цитируемый пост)
Мне надо задать 400 функций для всех комбинаций параметров CSize, RSize.  

вот набросок на скорую руку  : http://liveworkspace.org/code/113cae60cbf892e1eb9bd90b3c193ec8
 ловите, и допиливаете под свои нужды smile 

Автор: W4FhLF 12.10.2010, 12:13
mes, да, то что нужно! Спасибо большое. smile 

Автор: mes 12.10.2010, 12:47
Цитата(W4FhLF @  12.10.2010,  10:23 Найти цитируемый пост)
 в диапазоне 5-25 скажем. Т.е. может быть 400 комбинаций,

скорее всего  опечатка, но на всякий случай уточню ..  в данном диапазоне 442smile 441 вариант... 
и тогда не 20
Код

(c-5)*20+(r-5)

а 21
smile

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

Автор: W4FhLF 12.10.2010, 12:49
Цитата(mes @  12.10.2010,  12:47 Найти цитируемый пост)
мож опечатка, но на всякий случай уточню ..  в данном диапазоне 442 варианта... 


Минимальное значение параметра 1. Я это буду учитывать. Да, ессно уже юзаю двумерный массив )

Добавлено через 10 минут и 22 секунды
Компилятор ругается. :( 

Цитата

Error    32    error: excessive recursion at instantiation of function "initKernels<N>() [with N=2341U]"


Добавлено через 11 минут и 49 секунд
Error    95    error: excessive recursion at instantiation of function "initKernels<N>() [with N=241U]"

И даже так

Автор: EgorTheBlade 12.10.2010, 13:17
поставте ограничение на рекурсию.

Автор: mes 12.10.2010, 13:17
не хватает "мощности" Вашего компилятора, дробите инициализацию на несколько частей.. 

Автор: W4FhLF 12.10.2010, 13:50
Хыхы, да это понятно, что компилятор заткнулся из-за большой вложенности. smile Похоже у него порог 200. Пока никаких ключей чтобы увеличить уровень вложенности найти не могу. Придётся делить видимо. 

Автор: mes 12.10.2010, 14:19
Цитата(W4FhLF @  12.10.2010,  12:50 Найти цитируемый пост)
Придётся делить видимо.  

насколько я понимаю, для уменьшения рекурсии, можно линейный цикл привести к матричному :
http://liveworkspace.org/code/8e5924a199e81cec904cfb80ab61209c

Добавлено @ 14:20
эх давно не метапрограммировал.. подзабылось уже.. 

Добавлено @ 14:21
P.S. вместо Аction подставить инициализацию массива, разумеется.. 
smile

Автор: boostcoder 12.10.2010, 14:22
а про табуляцию все же подзабыли ;)

Автор: mes 12.10.2010, 14:23
Цитата(boostcoder @  12.10.2010,  13:22 Найти цитируемый пост)
а про табуляцию все же подзабыли ;) 

ага.. по старой привычке.. 


Добавлено через 44 секунды
boostcoder, и где код базового класса из соседней темы ? устал ждать )) 

Автор: boostcoder 12.10.2010, 14:28
именно над этим и работаю в данный момент)

Автор: W4FhLF 12.10.2010, 14:30
mes, очень красиво. smile Буду пробовать.

А код я всё же сюда вставлю, чтобы он в нашей базе хранился:

Код

#include <iostream>

template <size_t C, size_t R>
void Action() {
   std::cout << C <<"," << R << std::endl;
}

template<size_t C, size_t R > 
struct forR { 
    static void Do() 
    {
         Action<C,R>(); 
         forR<C, R-1>::Do();
    } 
};

template<size_t C> 
struct forR<C,0> {   
    static void Do() 
    {
       Action<C,0>();
    }
};
template<size_t C, size_t R > 
struct forC { 
    static void Do() 
    {   
         forR<C,R>::Do(); 
         forC<C-1, R>::Do();
    } 
};

template<size_t R> 
struct forC<0, R> {   
    static void Do() 
    {
        forR<0,R>::Do();     
    }
};

int main () 
{
   forC<20,20> ::Do();      
}

Автор: W4FhLF 12.10.2010, 14:58
Объектиники тем временем получаются по 10-15 мб и собираются пару минут. smile Правда очень хорошо жмутся UPX'ом, в 20 раз. Ещё раз спасибо mes'у за решение. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)