Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
| | | | |
[C++] Извините, но это все фигня 06.02.02 17:48 Число просмотров: 860
Автор: cb <cb> Статус: Member
|
> Хотелось бы перевести обсуждение в другое "русло", не как > выключить оптимизацию, а как указать оптимизатору > что чтение из памяти имеет сторонний эффект.
к сожалению после установки очередного патча на MSVC6 оптимизация у меня вообще похоже вырубилась, так что проверить не могу, но можешь попробовать это
void MyFunc(volatile unsigned *MyPtr)
{
unsigned dummy;
dummy = *MyPtr;
dummy ^= dummy;
dummy |= *MyPtr;
}
---
|
<programming>
|
[C++] Ну все, спасайте меня :-) MS VC++ 7.0 05.02.02 09:58
Автор: leo <Леонид Юрьев> Статус: Elderman
|
Есть такой зверь MS Visual Studio .NET beta2, а в нем VC++ 7.0...
Компилятор там точно нормальный, потому что немного старше своего "брата" из WinXP DDK.
Суть борьбы вот в чем:
Нужно заставить компилятор не "свертывать" чтение по указателю, результат которого не используется. Например имеем код:
void MyFunc(volatile unsigned *MyPtr)
{
unsigned dummy;
dummy = *MyPtr;
dummy = *MyPtr;
} ---
При полной оптимизации (/Oxa) компилятор убивает обращения к *MyPtr, а их нужно оставить. Потому что MyPtr указывает на Memory Mapped I/O Space и чтение *MyPtr аналогично __asm in al, dx
До включения полной потимизации было достаточно volatile-спецификатора, что сейчас делать не знаю. Конечно можно тупо написать функцию чтения, но в данном случае нужно максимально быстро, и затраты на вызов функции существенны.
Было-бы интересно узнать, как указать компилятору что функция (или выражение) имеет некий side-effect и не допускает удаления, как например _inp(). Например GCC имеет для этого все средства...
|
|
[C++] Ну все, спасайте меня :-) MS VC++ 7.0 05.02.02 22:02
Автор: + <Mikhail> Статус: Elderman
|
A eto ne rabotaet?
#pragma optimize( "", off )
void MyFunc(volatile unsigned *MyPtr)
{
unsigned dummy;
dummy = *MyPtr;
dummy = *MyPtr;
}
#pragma optimize( "", on )
---
|
| |
[C++] Оптимизацию выключать нельзя, потому что использутся шаблоны 05.02.02 22:34
Автор: leo <Леонид Юрьев> Статус: Elderman
|
|
| | |
[C++] Оптимизацию выключать нельзя, потому что использутся шаблоны 05.02.02 23:31
Автор: + <Mikhail> Статус: Elderman
|
Ne vizhu ni kakoi sviazi.
No a esli vse zhe nastaivaesh togda bot tak:
void MyFunc(volatile unsigned *MyPtr)
{
unsigned dummy;
#pragma optimize( "", off )
dummy = *MyPtr;
dummy = *MyPtr;
#pragma optimize( "", on )
}
---
|
| | | |
[C++] Извините, но это все фигня 06.02.02 10:10
Автор: leo <Леонид Юрьев> Статус: Elderman
|
1) RTFM - #pragma допустима только вне функции, вне декларации, вне шаблона;
2) RTFM - При глобальной "Whole Program Optimization" компилятор все равно убьет все функции без сторонних эффектов, результат которых не используеться;
3) RTFM - чтобы гарантированно выключить оптимизацию в шаблоне, ее нужно выключить везде где этот шаблон используется;
Оптимизацию выключать вообще не выгодно и не удобно. Лучше сделать несколько внешних (недоступных) оптимзатору функций, которые будут выполнять чтение или "делать вид" использования результата. Пока я так и сделал: volatile-чтения, результат которых не используется, сейчас передается параметром в недоступную оптимизатору dummy-функцию .
Это решение не нравится прежде всего тем, что вызов внешней функции(равно как и __asm-вставка) заставляет компилятор перезагружать значение регистров их памяти, и в итоге увеличивае размер кода в ~5 раз.
Хотелось бы перевести обсуждение в другое "русло", не как выключить оптимизацию, а как указать оптимизатору что чтение из памяти имеет сторонний эффект.
|
| | | | |
[C++] Извините, но это все фигня 06.02.02 17:48
Автор: cb <cb> Статус: Member
|
> Хотелось бы перевести обсуждение в другое "русло", не как > выключить оптимизацию, а как указать оптимизатору > что чтение из памяти имеет сторонний эффект.
к сожалению после установки очередного патча на MSVC6 оптимизация у меня вообще похоже вырубилась, так что проверить не могу, но можешь попробовать это
void MyFunc(volatile unsigned *MyPtr)
{
unsigned dummy;
dummy = *MyPtr;
dummy ^= dummy;
dummy |= *MyPtr;
}
---
|
| | | | | |
[C++] Извините, но ещё фигня 08.02.02 02:49
Автор: Biasha <Бяша> Статус: Member
|
А ещё можно вот так:
void MyFunc(volatile unsigned *MyPtr)
{
unsigned dummy;
for(dummy = *MyPtr;dummy = *MyPtr;)
break;
} ---
или так:
void MyFunc(volatile unsigned *MyPtr)
{
unsigned dummy;
dummy = *MyPtr;
{dummy = *MyPtr;}
} ---
Только, к сожалению, всё это благодаря ограниченности интеллекта оптимизатора, а значит может и не работать на следующих его версиях.
|
| | | | | | |
[C++] Оптимизатор VC++ 7.0 все это "кушает" 08.02.02 07:26
Автор: leo <Леонид Юрьев> Статус: Elderman
|
|
|
[C++] Ну все, спасайте меня :-) MS VC++ 7.0 05.02.02 13:30
Автор: cb <cb> Статус: Member
|
> к *MyPtr, а их нужно оставить. Потому что MyPtr указывает > на Memory Mapped I/O Space и чтение *MyPtr аналогично __asm > in al, dx
а на сколько принципиально использование именно Memory Mapped I/O Space? может быть можно обойтись именно in al, dx?
cb.
|
| |
[C++] Это все разговоры, а нужно решение 05.02.02 14:24
Автор: leo <Леонид Юрьев> Статус: Elderman
|
> а на сколько принципиально использование именно Memory > Mapped I/O Space? может быть можно обойтись именно in al, > dx?
Во-первых: Memory Mapped I/O работает со скоросью шины (PCI/AGP и т.д.), а Port I/O со скоротью ISA. А мне именно скорость и нужна.
Во-вторых: не переделывать ведь железку из-за dummy-компилятора :-)
|
| | |
[C++] Это все разговоры, а нужно решение 05.02.02 14:40
Автор: cb <cb> Статус: Member
|
а что это уже не работает?
#pragma optimize( "", off )
.
.
.
#pragma optimize( "", on )
|
| | | |
[C++] Re: Это все разговоры, а нужно решение 05.02.02 16:30
Автор: leo <Леонид Юрьев> Статус: Elderman
|
Выключение оптимизации конечно даст нужный эффект. Но я использую шаблоны, поэтому если идти этим путем, то выключать потимизаци. нужно вообще...
Сейчас я вызываю внешнюю пустую dummy-функцию, которая кроме RET ничего не далеет.
Примерно так:
void __fastcall DummyVolatileNoop(const unsigned __int8 dummy);
void __fastcall DummyVolatileNoop(const unsigned __int16 dummy);
void __fastcall DummyVolatileNoop(const unsigned __int32 dummy);
...
template <bool MemoryMapped, bool IoPause> class THardwareIo
{
public:
...
template <typename type> __forceinline static void CommitVolatileRead(const type Value)
{
if(MemoryMapped)
DummyVolatileNoop(Value);
}
...
}
...
template <class THardwareIo> class CL_VGA
{
public:
LyWin2000Kernel::THardwareIoAddress FrameBufferAddress;
LyWin2000Kernel::THardwareIoAddress BaseIoAddress;
LyWin2000Kernel::THardwareIoAddress ExRomAddress;
LyWin2000Kernel::THardwareIoAddress GpioAddress;
....
__forceinline void WriteHiddenDAC(const unsigned __int8 value) const // hirgwr
{
THardwareIo::CommitVolatileRead(
ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
| ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
| ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
| ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
);
WriteRegisterByte(VGA_VideoDacPixelMask_HiddenDac, value);
}
__forceinline unsigned __int8 ReadHiddenDAC() const // hirgrd
{
THardwareIo::CommitVolatileRead(
ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
| ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
| ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
| ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac)
);
return ReadRegisterByte(VGA_VideoDacPixelMask_HiddenDac);
}
...
// ------------- extern asm-файл
[section .text]
[global ?DummyVolatileNoop@LyWin2000Kernel@@YIXPBX@Z]
[global ?DummyVolatileNoop@LyWin2000Kernel@@YIX_K@Z]
...
[global ?ReadVolatileQuad@LyWin2000Kernel@@YI_KK@Z]
[global ?ReadVolatileLong@LyWin2000Kernel@@YIIK@Z]
[global ?ReadVolatileWord@LyWin2000Kernel@@YIGK@Z]
[global ?ReadVolatileByte@LyWin2000Kernel@@YIEK@Z]
?ReadVolatileByte@LyWin2000Kernel@@YIEK@Z:
mov al, [ecx]
?DummyVolatileNoop@LyWin2000Kernel@@YIXPBX@Z:
?DummyVolatileNoop@LyWin2000Kernel@@YIX_K@Z:
...
ret
?ReadVolatileWord@LyWin2000Kernel@@YIGK@Z:
mov ax, [ecx]
ret
?ReadVolatileLong@LyWin2000Kernel@@YIIK@Z:
mov eax, [ecx]
ret
?ReadVolatileQuad@LyWin2000Kernel@@YI_KK@Z:
mov eax, [ecx]
mov edx, [ecx + 4]
ret
---
|
| | | | |
[C++] Re: Это все разговоры, а нужно решение 05.02.02 16:54
Автор: cb <cb> Статус: Member
|
> Выключение оптимизации конечно даст нужный эффект. Но я > использую шаблоны, поэтому если идти этим путем, то > выключать потимизаци. нужно вообще...
почему?
cb.
|
| | | | | |
[C++] Скрытые директивы/ключевые слова VC++ 7.0 05.02.02 17:08
Автор: leo <Леонид Юрьев> Статус: Elderman
|
> > Выключение оптимизации конечно даст нужный эффект. Но > я > > использую шаблоны, поэтому если идти этим путем, то > > выключать потимизаци. нужно вообще... > > почему? > > cb.
Переключать оптимизацию внутри шаблона бесполезно. При генерации кода компилятор будет инсталлировать шаблоны с опциями оптимизации актуальными в месте инсталлирования. Вот и получается, что для получения нужного эффекта требуется выключить оптимизацию во всех фалах проекта, которые используют критический шаблон, и делее шаблоны которые используют это шаблон и т.д.
Это неприемлемо, гораздо проще и выгоднее вызвать внешнюю функции для "покрывания" так сказать "неприкрытого" чтения из Memory Mapped I/O Space.
Я надеюсь что кто-нибудь знает как включить доступ к скрытым директивам VC++ 7.0, и как их использовать, например _annonate, __feacpBreak __compileBreak, __pragma(plmn), __pragma(plmf), __pragma(native_caller) и т.д. Их видно в с1.dll
|
|
|