Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: [ТЧ,ЧН,ЗП] Многоядерность
GAMEINATOR forums > S.T.A.L.K.E.R. > Мастерская: создание модов для S.T.A.L.K.E.R.
Страницы: 1, 2
Stalker_Monolit
Перед прочтением прошу сильно не ругать если что это моя первая тема тут unsure.gif
Перед история поиска или как я нашел строчку - это можно прочесть по желанию.
Начну с того что я как я любитель билдоман и уже вошла в привычку моя поисковая сноровка, и она меня не подвила laugh.gif я начал свой день с того что мне захотелось найти в исходниках X-Ray те строки которые отвечают за использование процессора и я начал эти поиски и они прошли недолго часика так за 4-5 в поиске через Notepad++ я сначала нашел вот эти подозрительные строки.
Клац
// Фунция для тупых требований THQ и тупых американских пользователей
BOOL IsOutOfVirtualMemory()
{
#define VIRT_ERROR_SIZE 256
#define VIRT_MESSAGE_SIZE 512

SECUROM_MARKER_HIGH_SECURITY_ON(1)

MEMORYSTATUSEX statex;
DWORD dwPageFileInMB = 0;
DWORD dwPhysMemInMB = 0;
HINSTANCE hApp = 0;
char pszError[ VIRT_ERROR_SIZE ];
char pszMessage[ VIRT_MESSAGE_SIZE ];

ZeroMemory( &statex , sizeof( MEMORYSTATUSEX ) );
statex.dwLength = sizeof( MEMORYSTATUSEX );

if ( ! GlobalMemoryStatusEx( &statex ) )
return 0;

dwPageFileInMB = ( DWORD ) ( statex.ullTotalPageFile / ( 1024 * 1024 ) ) ;
dwPhysMemInMB = ( DWORD ) ( statex.ullTotalPhys / ( 1024 * 1024 ) ) ;

// Довольно отфонарное условие
if ( ( dwPhysMemInMB > 500 ) && ( ( dwPageFileInMB + dwPhysMemInMB ) > 2500 ) )
return 0;

hApp = GetModuleHandle( NULL );

if ( ! LoadString( hApp , RC_VIRT_MEM_ERROR , pszError , VIRT_ERROR_SIZE ) )
return 0;

if ( ! LoadString( hApp , RC_VIRT_MEM_TEXT , pszMessage , VIRT_MESSAGE_SIZE ) )
return 0;

MessageBox( NULL , pszMessage , pszError , MB_OK | MB_ICONHAND );

SECUROM_MARKER_HIGH_SECURITY_OFF(1)

return 1;
}

Немного посмотрев на них я подумал может это ограничение использование видео памяти но после того как я тут отписался меня в этом переубедили laugh.gif Пост но главное суть я понял. Немного полистав в глубь x_ray.cpp я увидел вот это:
CODE
#endif
#else // DEDICATED_SERVER
g_dedicated_server = true;
#endif // DEDICATED_SERVER

SetThreadAffinityMask (GetCurrentThread(),1);

// Title window
// Картинка при старте
logoWindow = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_STARTUP), 0, logDlgProc );


HWND logoPicture = GetDlgItem(logoWindow, IDC_STATIC_LOGO);
RECT logoRect;
GetWindowRect(logoPicture, &logoRect);

SetWindowPos (
logoWindow,

И тут я немного погуглил и сказав не может быть начал быстренько собирать сорцы но при этом поменяв цифру 1 на 2 и был приятно удивлен мой гаджет на боковой панели показал усердное использование второго ядра, не долго думая я поставил цифру 0 и попробовав я увидел свое счастье два процессора работают и диспетчер задач показывает что xrEngine использует 70% ЦП УРА!!! Можно танцевать!!! laugh.gif

Как использовать два и более ядер
Немного загуглив я нашел некую информацию как использовать больше ядер но для этого нужно пере-собирать исходники заново потому что я эту цифру 1 рядом с GetCurrentThread в пысовском движке так и не вцепил через HEX-Editor может это кому то другому удастся.

Строка в коде x_ray.cpp
Код
    // Use CPU
    SetThreadAffinityMask        (GetCurrentThread(),1);


Что можно подставить - спасибо другу asdandgamer
Код
The mask is a bitfield: each bit designate a processor. 0 means "no processor". It's not logic.
0x0001 : proc 1
0x0003 : proc 1 and 2
0x000F : proc 1, 2, 3, 4

Так что можно сразу сделать так:
Код
    // Use CPU
    SetThreadAffinityMask        (GetCurrentThread(),0x000F);

Будет использоваться 4 ядра и более.
Полезная ссылка по этим строкам Ссылка
cjayho
А вам не кажется, что намного проще закомментарить строчку SetThreadAffinityMask (GetCurrentThread(),1); ?

Но только учтите, что многоядерности от этого не появится (для этого нужно переписывать код на предмет распараллеливания операций по отдельным потокам), только анимации и видео будут проигрываться тем быстрее, чем больше ядер у процессора. Начиная от двукратного прироста, четверократного для четырехъядерного и так далее в линейной прогрессии.

Ps. В смысле возрастет не FPS, а именно скорость их проигрывания, то есть секундная анимация будет отыгрываться за полсекунды на двуядерном проце, четверть секунды на четырехъядерном и так далее.
Stalker_Monolit
Цитата(cjayho @ 10.08.2015, 17:53) *
Но только учтите, что многоядерности от этого не появится

Почему это? blink.gif Не может мне компьютер наврать что он два процессора не юзал.
jamakasi
Stalker_Monolit, многоядерность будет но совсем не та что нужна laugh.gif
Cossack-HD
Снижение time_factor до 0.5 приводит в ощутимому увеличению FPS, что какбэ намекает, что даже в LA с её ЗПподобной "многоядерностью" на одном ядре висит не только графон, но и куча всего типа логики, физики, звука и анимаций (их апдейт замедляется и у ядра остаётся больше времени на отрисовку графонов - вырастает FPS).
Если оставить логику, физику, скрипты и анимации на одном ядре, а рендер почти полностью перенести на другое, то производительность должна улучшиться.
Stalker_Monolit
Цитата(Cossack-HD @ 10.08.2015, 19:20) *
Снижение time_factor до 0.5 приводит в ощутимому увеличению FPS, что какбэ намекает, что даже в LA с её ЗПподобной "многоядерностью" на одном ядре висит не только графон, но и куча всего типа логики, физики, звука и анимаций (их апдейт замедляется и у ядра остаётся больше времени на отрисовку графонов - вырастает FPS).
Если оставить логику, физику, скрипты и анимации на одном ядре, а рендер почти полностью перенести на другое, то производительность должна улучшиться.

blink.gif А сорцы LA разве уже в сети плавают?
Если это так то можно было это сделать как и разрабы сделали, только дописать пару кусочков кода в нужные dll-ки меняя при этом какой проц будет юзатся.
jamakasi
Stalker_Monolit, если б было все так просто то уже давным давно бы сделали многопоточку нормальную. Тут слишком многое нужно переделывать в движке. Просто так прописать что вот это должно обсчитываться на этом ядре не получится т.к. потоки должны взаимодействовать друг с другом, ожидать друг друга на блокировках и т.д. . Задача хоть и подсильная но слишком нереально геморойная. Проще пользуйся тем что есть, компы из года в год только растут мощностью поэтому теребонькать на что-то ненужное(многопоточность) бессмысленно, вот 64 битка имеет смысл в игре а многоядерность не особо.К примеру мой комп довольно легко тащит LA(сглаживания не максимальные только и дальность травки).
Билдоман
Stalker_Monolit,

Плавают, более того, лежат в отдельной теме. http://www.gameru.net/forum/index.php?show...p;#entry1553432
Stalker_Monolit
Цитата(Билдоман @ 11.08.2015, 01:18) *
Stalker_Monolit,

Плавают, более того, лежат в отдельной теме. http://www.gameru.net/forum/index.php?show...p;#entry1553432

Спасибо а то я думал с другого ресурса качать smile.gif
Stalker_Monolit
Заметил что сталкер использует расширение функциональности Boost который по копирайту
Цитата
Copyright © 2001-2003
не обновлялся с 2003 гада может попробовать обновить ее? Там же есть и использование потоков и тайминг короче корни для оптимизации тянутся оттуда.
abramcumner
Stalker_Monolit, думаешь после обновления вызовы потоков, тайминги и корни сами вырастут из воздуха?

А и обнови, кстати. Хорошая задачка для начала.
RedMagic
Цитата(abramcumner @ 12.08.2015, 18:00) *
Stalker_Monolit, думаешь после обновления вызовы потоков, тайминги и корни сами вырастут из воздуха?

Вангую что сначала все поломается и куча времени будут потрачена на то чтобы "вернуть все как было" biggrin.gif
abramcumner
Совсем нет. Поломается, но не прямо уж все smile.gif Вот луабинд обновить...

Кстати, в ЛА-исходниках не новый разве буст?
Tron
Вот luabind как раз и поломается. Он кажется зависит от темплейта удаленного в последних версиях
По сути boost используется только luabind'ом
-StalkMen-
Я обновил boost, только теперь сам не знаю зачем laugh.gif
Разве что опыт biggrin.gif
abramcumner
-StalkMen-, многоядерность поперла?

Теперь луабинд на очереди smile.gif
Samaritan
Цитата(abramcumner @ 14.08.2015, 14:13) *
Теперь луабинд на очереди

Запилить бы визуальное программирование, подгрузку текстур, продвинутую систему LOD, лицевую анимацию, PhysX или Havok и пожалуй Scaleform.
RedMagic
Цитата(lambdist @ 14.08.2015, 13:34) *
Цитата(abramcumner @ 14.08.2015, 14:13) *
Теперь луабинд на очереди

Запилить бы визуальное программирование, подгрузку текстур, продвинутую систему LOD, лицевую анимацию, PhysX или Havok и пожалуй Scaleform.

А может ещё и удобный WYSIWYG редактор? biggrin.gif Это уже будет totstalkir.gif
-StalkMen-
Цитата(abramcumner @ 14.08.2015, 13:13) *
Теперь луабинд на очереди

Я их одновременно обновлял rolleyes.gif
С луабиндом гораздо больше заморочек, начиная от переписываниЙ© в xrGame, заканчивая переписыванием скриптов sad.gif

Цитата(abramcumner @ 14.08.2015, 13:13) *
многоядерность поперла?

От обновления boost'а?.. o_O.gif

Цитата(lambdist @ 14.08.2015, 13:34) *
PhysX

Пилю потихоньку wink_old.gif Пока всё нравится, правда мануалов на Русском мало sad.gif
Начал с замены xrCDB (для компиля)
abramcumner
Цитата(-StalkMen- @ 14.08.2015, 15:15) *
От обновления boost'а?.. o_O.gif

Конечно, его же именно для этого предлагалось обновить smile.gif
-StalkMen-
Мне вообще кажется, что надо boost вырезать из luabind'а. А вместо него использовать плюшки C++0x.

Что-то вроде такого
Было

Код
// new(1)
template <class T, class P1>
IC    T*        xr_new        (const P1& p1) {
    T* ptr    = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
    return new (ptr) T(p1);
}
// new(2)
template <class T, class P1, class P2>
IC    T*        xr_new        (const P1& p1, const P2& p2) {
    T* ptr    = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
    return new (ptr) T(p1,p2);
}
// new(3)
template <class T, class P1, class P2, class P3>
IC    T*        xr_new        (const P1& p1, const P2& p2, const P3& p3) {
    T* ptr    = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
    return new (ptr) T(p1,p2,p3);
}


Стало
Код
// new()
template <class T, class ... Args>
IC    T*        xr_new(const Args& ... args)
{
    T* ptr    = (T*)Memory.mem_alloc(sizeof(T));
    return new (ptr)T(args...);
}
abramcumner
Цитата(-StalkMen- @ 14.08.2015, 15:35) *
Мне вообще кажется, что надо boost вырезать из luabind'а. А вместо него использовать плюшки C++0x.

Кто-то уже вырезал. Может Tron?
Stalker_Monolit
Цитата(-StalkMen- @ 14.08.2015, 15:35) *
// new(1)
template <class T, class P1>
IC    T*        xr_new        (const P1& p1) {
    T* ptr    = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
    return new (ptr) T(p1);
}
// new(2)
template <class T, class P1, class P2>
IC    T*        xr_new        (const P1& p1, const P2& p2) {
    T* ptr    = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
    return new (ptr) T(p1,p2);
}
// new(3)
template <class T, class P1, class P2, class P3>
IC    T*        xr_new        (const P1& p1, const P2& p2, const P3& p3) {
    T* ptr    = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
    return new (ptr) T(p1,p2,p3);
}

А ты разве свой проект в debug режиме слаживаешь? Первая строка DEBUG_MEMORY_NAME
Клац
#ifdef DEBUG_MEMORY_NAME
// new(0)
template <class T>
IC T* xr_new ()
{
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T();
}
// new(1)
template <class T, class P1>
IC T* xr_new (const P1& p1) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1);
}
// new(2)
template <class T, class P1, class P2>
IC T* xr_new (const P1& p1, const P2& p2) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2);
}
// new(3)
template <class T, class P1, class P2, class P3>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2,p3);
}
// new(4)
template <class T, class P1, class P2, class P3, class P4>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2,p3,p4);
}
// new(5)
template <class T, class P1, class P2, class P3, class P4, class P5>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2,p3,p4,p5);
}
// new(6)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2,p3,p4,p5,p6);
}
// new(7)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2,p3,p4,p5,p6,p7);
}
// new(8)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2,p3,p4,p5,p6,p7,p8);
}
// new(9)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8, const P8& p9) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T), typeid(T).name());
return new (ptr) T(p1,p2,p3,p4,p5,p6,p7,p8,p9);
}
#else // DEBUG_MEMORY_NAME
// new(0)
template <class T>
IC T* xr_new ()
{
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T();
}
// new(1)
template <class T, class P1>
IC T* xr_new (const P1& p1) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1);
}
// new(2)
template <class T, class P1, class P2>
IC T* xr_new (const P1& p1, const P2& p2) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2);
}
// new(3)
template <class T, class P1, class P2, class P3>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2,p3);
}
// new(4)
template <class T, class P1, class P2, class P3, class P4>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2,p3,p4);
}
// new(5)
template <class T, class P1, class P2, class P3, class P4, class P5>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2,p3,p4,p5);
}
// new(6)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2,p3,p4,p5,p6);
}
// new(7)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2,p3,p4,p5,p6,p7);
}
// new(8)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2,p3,p4,p5,p6,p7,p8);
}
// new(9)
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
IC T* xr_new (const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8, const P8& p9) {
T* ptr = (T*)Memory.mem_alloc(sizeof(T));
return new (ptr) T(p1,p2,p3,p4,p5,p6,p7,p8,p9);
}
#endif // DEBUG_MEMORY_NAME
-StalkMen-
Stalker_Monolit,
Обычно нет, мой ДеБуг, это Mixed (Копия Release без оптимизации)
Клац
Stalker_Monolit
Цитата(-StalkMen- @ 14.08.2015, 17:16) *
Stalker_Monolit,
Обычно нет, мой ДеБуг, это Mixed (Копия Release без оптимизации)
Клац

Понятно blush1.gif ты не знаешь что за приоритеты выставлены почти каждому проекту?
R1
Код
Device.seqFrame.Add    (this,REG_PRIORITY_HIGH+0x12345678);

R2
Код
Device.seqFrame.Add    (this,REG_PRIORITY_HIGH+0x12345678);

R3
Код
Device.seqFrame.Add    (this,REG_PRIORITY_HIGH+0x12345678);

И мне кажется есть связь с pure.h в котором вот это:
Клац
#ifndef _PURE_H_AAA_
#define _PURE_H_AAA_

// messages
#define REG_PRIORITY_LOW 0x11111111ul
#define REG_PRIORITY_NORMAL 0x22222222ul
#define REG_PRIORITY_HIGH 0x33333333ul
#define REG_PRIORITY_CAPTURE 0x7ffffffful
#define REG_PRIORITY_INVALID 0xfffffffful

typedef void __fastcall RP_FUNC (void *obj);
#define DECLARE_MESSAGE(name) extern ENGINE_API RP_FUNC rp_##name; class ENGINE_API pure##name { public: virtual void On##name(void)=0; }
#define DECLARE_RP(name) void __fastcall rp_##name(void *p) { ((pure##name *)p)->On##name(); }

DECLARE_MESSAGE(Frame);
DECLARE_MESSAGE(Render);
DECLARE_MESSAGE(AppActivate);
DECLARE_MESSAGE(AppDeactivate);
DECLARE_MESSAGE(AppStart);
DECLARE_MESSAGE(AppEnd);
DECLARE_MESSAGE(DeviceReset);

//-----------------------------------------------------------------------------
struct _REG_INFO {
void* Object;
int Prio;
u32 Flags;
};

ENGINE_API extern int __cdecl _REG_Compare(const void *, const void *);

template <class T> class CRegistrator // the registrator itself
{
friend ENGINE_API int __cdecl _REG_Compare(const void *, const void *);
public:
xr_vector<_REG_INFO> R;
// constructor
struct {
u32 in_process :1;
u32 changed :1;
};
CRegistrator() { in_process=false; changed=false;}

//
void Add (T *obj, int priority=REG_PRIORITY_NORMAL, u32 flags=0)
{
#ifdef DEBUG
VERIFY (priority!=REG_PRIORITY_INVALID);
VERIFY (obj);
for (u32 i=0; i<R.size(); i++) VERIFY( !((R[i].Prio!=REG_PRIORITY_INVALID)&&(R[i].Object==(void*)obj)) );
#endif
_REG_INFO I;
I.Object =obj;
I.Prio =priority;
I.Flags =flags;
R.push_back (I);

if(in_process) changed=true;
else Resort ( );
};
void Remove (T *obj)
{
for (u32 i=0; i<R.size(); i++) {
if (R[i].Object==obj) R[i].Prio = REG_PRIORITY_INVALID;
}
if(in_process) changed=true;
else Resort ( );
};
void Process(RP_FUNC *f)
{
in_process = true;
if (R.empty()) return;
if (R[0].Prio==REG_PRIORITY_CAPTURE) f(R[0].Object);
else {
for (u32 i=0; i<R.size(); i++)
if(R[i].Prio!=REG_PRIORITY_INVALID)
f(R[i].Object);

}
if(changed) Resort();
in_process = false;
};
void Resort (void)
{
qsort (&*R.begin(),R.size(),sizeof(_REG_INFO),_REG_Compare);
while ((R.size()) && (R[R.size()-1].Prio==REG_PRIORITY_INVALID)) R.pop_back();
if (R.empty()) R.clear ();
changed = false;
};
};

#endif
-StalkMen-
Stalker_Monolit,
Приоритет - выше высокого.
Tron
Цитата(abramcumner @ 14.08.2015, 16:11) *
Цитата(-StalkMen- @ 14.08.2015, 15:35) *
Мне вообще кажется, что надо boost вырезать из luabind'а. А вместо него использовать плюшки C++0x.

Кто-то уже вырезал. Может Tron?


Не, я этим не занимался. Хотел, но не сделал.
То,что по ссылке выше там же вариадик темплейты, их поддержка только в 13ой студии появилась.
Есть форк луабинда, там С++11 плюшки есть, но собирается и с более ранней студией(с 12 точно)

Added:
Версию с новым луабиндом делал codepoet, но у него что-то там не срослось,ибо он не довел ее
Tron
Сегодня курил код, нашел механизм работы с потоками. Точнее, я его и до этого видел, но сегодня я прям отладчиком на него попал

Многопоточный рендер там точно есть(ему выделен 1 дополнительный поток, помимо основного).
Даже есть команда для мнгп. окклуюжена
-StalkMen-
Tron,
Цитата(Tron @ 23.08.2015, 09:37) *
1 дополнительный поток

"X-RAY Secondary thread" Этот?

На сколько я знаю, оба потока работают последовательно sad.gif

Тогда где же тут
Цитата(Tron @ 23.08.2015, 09:37) *
Многопоточный рендер

???
MegaNub
Цитата(Tron @ 12.08.2015, 20:01) *
По сути boost используется только luabind'ом

В xrNetServer для расчёта CRC?
Tron
Цитата(-StalkMen- @ 23.08.2015, 15:36) *
Tron,
Цитата(Tron @ 23.08.2015, 09:37) *
1 дополнительный поток

"X-RAY Secondary thread" Этот?

На сколько я знаю, оба потока работают последовательно sad.gif

Тогда где же тут
Цитата(Tron @ 23.08.2015, 09:37) *
Многопоточный рендер

???

в консольных командах есть r2_mt

Но вообще я возможно ошибся

Цитата(MegaNub @ 23.08.2015, 16:22) *
В xrNetServer для расчёта CRC?

можно легко заменить на вариант из zlib
-StalkMen-
Цитата(Tron @ 24.08.2015, 05:43) *
r2_mt

Код
void CRender::OnFrame()
{
    Models->DeleteQueue            ();
    if (ps_r2_ls_flags.test(R2FLAG_EXP_MT_CALC))    {
        // MT-details (@front)
        Device.seqParallel.insert    (Device.seqParallel.begin(),
            fastdelegate::FastDelegate0<>(Details,&CDetailManager::MT_CALC));

        // MT-HOM (@front)
        Device.seqParallel.insert    (Device.seqParallel.begin(),
            fastdelegate::FastDelegate0<>(&HOM,&CHOM::MT_RENDER));
    }
}

Что-то есть, но Много Поточности нема laugh.gif
Neo][
Цитата(-StalkMen- @ 24.08.2015, 16:37) *
Что-то есть, но Много Поточности нема

-StalkMen-, почему такой вывод?
abramcumner
Три(основной+MT-details+MT-HOM) это разве много? z_lol1.gif
Neo][
Цитата(abramcumner @ 24.08.2015, 18:26) *
Три(основной+MT-details+MT-HOM) это разве много?

Ну, только если так смотреть, тогда действительно нема ))
Tron
Цитата(abramcumner @ 24.08.2015, 16:26) *
Три(основной+MT-details+MT-HOM) это разве много? z_lol1.gif


Цитата(Neo][ @ 24.08.2015, 16:35) *

Цитата(abramcumner @ 24.08.2015, 18:26) *
Три(основной+MT-details+MT-HOM) это разве много?

Ну, только если так смотреть, тогда действительно нема ))


Если так рассуждать, то у меня для вас очень плохие новости..

Во первых Occlusion Query очень дорогая операция, и ее результат будет доступен только через 1-5 кадров, после вызова.
- я лично с этим столкнулся. Да, долго не верил, т.к на моей машине это было незаметно, но запустив на старой машине, я получил прирост почти в 2 раза.
А все из-за чего? - ждем ответа от CPU.
Т.Е в теории это должно повысить производительность

Во вторых, сама операция создания треда, очень дорогая, и ее должно быть как можно меньше. Поэтому и используется Task-Based подход
Neo][
Tron, sarcasm.gif
-StalkMen-
Цитата(Neo][ @ 24.08.2015, 15:58) *

почему такой вывод?

Код
void             mt_Thread    (void *ptr)    {
    while (true) {
        // waiting for Device permission to execute
        Device.mt_csEnter.Enter    ();

        if (Device.mt_bMustExit) {
            Device.mt_bMustExit = FALSE;                // Important!!!
            Device.mt_csEnter.Leave();                    // Important!!!
            return;
        }
        // we has granted permission to execute
        mt_Thread_marker            = Device.dwFrame;

        for (u32 pit=0; pit<Device.seqParallel.size(); pit++)
            Device.seqParallel[pit]    ();
        Device.seqParallel.clear_not_free    ();
        Device.seqFrameMT.Process    (rp_Frame);

        // now we give control to device - signals that we are ended our work
        Device.mt_csEnter.Leave    ();
        // waits for device signal to continue - to start again
        Device.mt_csLeave.Enter    ();
        // returns sync signal to device
        Device.mt_csLeave.Leave    ();
    }
}

Один поток плодит работЫ, засыпает, другой их делает и засыпает о_О. И так по кругу. (Хоть основных потоков 2, но они работают, как один - последовательно)
Stalker_Monolit
Цитата(-StalkMen- @ 24.08.2015, 20:04) *
Хоть основных потоков 2, но они работают, как один - последовательно

Интересно если их сделать параллельно что то изменится? unsure.gif
Tron
Цитата(-StalkMen- @ 24.08.2015, 20:04) *
Один поток плодит работЫ, засыпает, другой их делает и засыпает о_О. И так по кругу. (Хоть основных потоков 2, но они работают, как один - последовательно)

Пояснить логику можешь?
Я вот смотрю и вижу другую логику работы, согласно данному семплу

И да, поток не засыпает, т.к нету вызова sleep_for или эквивалента
-StalkMen-
Tron,
не совсем так однако,
Основной поток плодит работы, да.
Во время рендеринга эти работы обрабатываются вторым потоком. Но из-за хитро*, есть вероятность, что эти работы будут просчитаны в том же потоке.
Tron
-StalkMen-, я вот не понимаю последние две строчки

Код
// now we give control to device - signals that we are ended our work
        Device.mt_csEnter.Leave    ();
        // waits for device signal to continue - to start again
        Device.mt_csLeave.Enter    ();
        // returns sync signal to device
        Device.mt_csLeave.Leave    ();

Это что-то типа маленькой синхронизации выступает?
-StalkMen-
Tron,
Да я тоже себе мозг этим сломал.
Код
    // Release start point - allow thread to run
    mt_csLeave.Enter            ();
    mt_csEnter.Leave            ();

Даём шанс 2 потоку стартовать.

Код
    // Release end point - allow thread to wait for startup point
    mt_csEnter.Enter                        ();
    mt_csLeave.Leave                        ();

Лочим. (Если 2 поток робит, то ждём его. Либо Не даём ему стартовать).


Код
    // Ensure, that second thread gets chance to execute anyway
    if (dwFrame!=mt_Thread_marker)            {
        for (u32 pit=0; pit<Device.seqParallel.size(); pit++)
            Device.seqParallel[pit]            ();
        Device.seqParallel.clear_not_free    ();
        seqFrameMT.Process                    (rp_Frame);
    }

Самый laugh.gif Если 2 поток не успел, то делаем его работу сами.

Вроде так.
Tron
А все понял, картина маслом.
Да походу ты прав
abramcumner
Вообще-то все немного не так или совсем не так smile.gif
Система простая: основной поток рендерит текущий кадр, во втором обсчитываются данные для следующего.
Второй поток не может не успеть - там же критические секции поставлены. Это значит, что он вообще не работал в этот раз. Без этой проверки будут тупо пропуски обсчета.
Neo][
-StalkMen-, заинтересовал, стяну завтра исходники посмотреть. Но вообще по фрагментам, которые ты привёл - там классическая задача поставщик- потребитель, а ты усложняешь )

Это ЗП?
-StalkMen-
Neo][,
Я что, я ничего biggrin.gif

Да, ЗП.
-StalkMen-
Цитата(Stalker_Monolit @ 24.08.2015, 20:07) *
Интересно если их сделать параллельно что то изменится?

Да. Вылетит один из потоков, проверил. Собственно этого следовало ожидать...

Neo][


Немного изменил для наглядности:
-StalkMen-
Neo][,
Хорошая картинка. Профилировщик?
Но а это ->
Код
if (dwFrame!=mt_Thread_marker)


Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.