Есть ли у OpenCL и OpenGL SL какое-либо неопределенное поведение?

Мне сказали, что C и C++ имеют «неопределенное поведение», то есть один и тот же код может вести себя по-разному на разных платформах или при использовании разных компиляторов, если я использую «определенные конструкции».

Относится ли то же самое к OpenCL и/или OpenGL SL?


person Sebastien Diot    schedule 17.09.2011    source источник


Ответы (4)


Да, согласно спецификации OpenCL 1.1, которая определяет неопределенное поведение в передний вопрос как:

Поведение вызова API OpenCL, встроенной функции, используемой внутри ядра, или выполнения ядра, которое явно не определено OpenCL. Соответствующая реализация не требуется для указания того, что происходит, когда в OpenCL встречается неопределенная конструкция.

Например:

  • Section 5.2.1 defines several:
    • "Reading from a buffer or image object created with CL_MEM_WRITE_ONLY inside a kernel"
    • "Запись в буфер или объект изображения, созданный с помощью CL_MEM_READ_ONLY внутри ядра"
    • «Команды OpenCL, которые работают с несколькими буферными объектами, созданными с одним и тем же host_ptr или перекрывающимися областями хоста»
    • «Одновременное чтение, запись и копирование между перекрывающимися объектами подбуфера, созданными с одним и тем же объектом буфера»
  • Section 5.2.2 also defines a few:
    • clEnqueueReadBuffer with other commands using the buffer
    • clEnqueueReadBuffer пока буфер отображается

Однако есть еще много способов вызвать неопределенное поведение из OpenCL.

Для OpenGL SL (спецификация) существует довольно много легко найти примеры:

  • «Неопределенное поведение возникает в результате индексации массива непостоянным выражением, которое больше или равно размеру массива или меньше 0» (интересно, если это const, то это ошибка времени компиляции)
  • Аналогично для доступа к векторным элементам с индексом массива.
  • «Чтение переменной переменной в вершинном шейдере возвращает неопределенные значения, если она читается перед записью»
  • «Если эта прагма [#pragma STDGL invariant(all)] используется после объявления любых переменных или функций, то набор выходных данных, которые ведут себя как инвариантные, не определен»
  • «Чтение [gl_PointSize или gl_ClipVertex] перед их записью приводит к неопределенному поведению»
  • и т. д.
person Flexo    schedule 17.09.2011
comment
Для справки, ответ Николя тоже точен - то, что вы описали как различное поведение на разных платформах, - это поведение, определяемое реализацией, не неопределенное поведение, которое намного хуже. - person Flexo; 18.09.2011

Да.

person w-m    schedule 17.09.2011

Мне сказали, что C и C++ имеют «неопределенное поведение», то есть один и тот же код может вести себя по-разному на разных платформах или при использовании разных компиляторов, если я использую «определенные конструкции».

Это не то, что на самом деле означает неопределенное поведение. Это результат неопределенного поведения, но оно не для этого.

Спецификации — это определение того, что происходит, когда вы что-то делаете. Он говорит, какие значения параметров хорошие, а какие плохие. Если вы пропускаете плохие, он сообщает вам, какие ошибки вы получаете и в каком состоянии будет система. Если текущее состояние недопустимо для операции, которую вы пытаетесь выполнить, в спецификации объясняется, какие другие типы ошибок вы получаете и что это означает для состояния системы впоследствии.

Когда вы используете определенное поведение, вы полагаетесь на контракт между вами и реализацией; этот контракт называется спецификацией OpenGL. Вы полагаетесь на реализацию, чтобы обеспечить проверки достоверности, требуемые спецификацией. И вы полагаетесь на то, что реализация делает то, что говорит спецификация. Если реализация не реализует что-то правильно, то она нарушает контракт.

Когда в спецификации говорится, что определенный набор вещей приведет к "неопределенному поведению", это означает, что выполнение этих действий означает, что вы нарушаете контракт. Вы находитесь за краем карты. Вы делаете что-то, для чего спецификация не обеспечивает определенного поведения; ты нарушил свою часть сделки.

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

Как правило, спецификация помечает что-то неопределенное, если его тестирование было бы обременительным бременем для реализаций. В конце концов, OpenGL должен быть достаточно быстрым. Таким образом, они стараются избегать обременения драйвера, заставляя его проверять вещи, которые почти невозможно проверить.

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

О, вы можете протестировать большую часть этого. Вы можете потерпеть неудачу при вызовах отрисовки, когда одна и та же текстура привязана к FBO и к сэмплеру. Но тогда вы не сможете рендерить одну и ту же текстуру в разные MIP-карты; помните: каждый мипмап — это отдельное изображение. Таким образом, вы можете проверить, допускает ли диапазон базового/максимального уровня возможность выборки из MIP-карты, привязанной к FBO. Но это ложится тяжелым бременем на пользователя, так как ему придется постоянно настраивать базовый/максимальный уровень при рендеринге в разные MIP-карты. Им гораздо проще просто взять образец из правильного MIP-карты с textureLOD или подобными функциями. И вы не можете определить до времени выполнения, делают ли они выборку из-за пределов этого уровня MIP-карты.

OpenCL и OpenGL SL имеют неопределенное поведение, как и многие спецификации. И, как правило, он не определен по тем же причинам: его тестирование сделало бы реализацию неприемлемо медленнее или тестирование было бы совершенно невозможным.

person Nicol Bolas    schedule 17.09.2011

Да, есть неопределенное поведение (вы можете просмотреть спецификацию, чтобы найти некоторые из них); но будьте осторожны, потому что это не единственный способ, которым программа может вести себя по-разному в разных системах: не все реализации OpenGL полностью компилируемы (на самом деле, вполне вероятно, что большинство из них таковыми не являются). Например, драйверы Nvidia позволяют здесь вызывать texture2D в профиле ядра, в то время как это вызывает ошибку на других платформах (и последнее является ожидаемым поведением). Лучший способ узнать, будет ли он работать, — протестировать его на нескольких платформах (ОС, GPU и драйверы).

person Mon ouïe    schedule 17.09.2011