Вы можете использовать ILP в CLI.Итак, короткий ответ: Нет.
Немного длиннее:
Я уже писал код для простой задачи по обработке изображений и использовал этот тип оптимизации, чтобы сделать мой код "немного" быстрее.
«Короткий» пример:
static void Main( string[] args )
{
const int ITERATION_NUMBER = 100;
TimeSpan[] normal = new TimeSpan[ITERATION_NUMBER];
TimeSpan[] ilp = new TimeSpan[ITERATION_NUMBER];
int SIZE = 4000000;
float[] data = new float[SIZE];
float safe = 0.0f;
//Normal for
Stopwatch sw = new Stopwatch();
for (int iteration = 0; iteration < ITERATION_NUMBER; iteration++)
{
//Initialization
for (int i = 0; i < data.Length; i++)
{
data[i] = 1.0f;
}
sw.Start();
for (int index = 0; index < data.Length; index++)
{
data[index] /= 3.0f * data[index] > 2.0f / data[index] ? 2.0f / data[index] : 3.0f * data[index];
}
sw.Stop();
normal[iteration] = sw.Elapsed;
safe = data[0];
//Initialization
for (int i = 0; i < data.Length; i++)
{
data[i] = 1.0f;
}
sw.Reset();
//ILP For
sw.Start();
float ac1, ac2, ac3, ac4;
int length = data.Length / 4;
for (int i = 0; i < length; i++)
{
int index0 = i << 2;
int index1 = index0;
int index2 = index0 + 1;
int index3 = index0 + 2;
int index4 = index0 + 3;
ac1 = 3.0f * data[index1] > 2.0f / data[index1] ? 2.0f / data[index1] : 3.0f * data[index1];
ac2 = 3.0f * data[index2] > 2.0f / data[index2] ? 2.0f / data[index2] : 3.0f * data[index2];
ac3 = 3.0f * data[index3] > 2.0f / data[index3] ? 2.0f / data[index3] : 3.0f * data[index3];
ac4 = 3.0f * data[index4] > 2.0f / data[index4] ? 2.0f / data[index4] : 3.0f * data[index4];
data[index1] /= ac1;
data[index2] /= ac2;
data[index3] /= ac3;
data[index4] /= ac4;
}
sw.Stop();
ilp[iteration] = sw.Elapsed;
sw.Reset();
}
Console.WriteLine(data.All(item => item == data[0]));
Console.WriteLine(data[0] == safe);
Console.WriteLine();
double normalElapsed = normal.Max(time => time.TotalMilliseconds);
Console.WriteLine(String.Format("Normal Max.: {0}", normalElapsed));
double ilpElapsed = ilp.Max(time => time.TotalMilliseconds);
Console.WriteLine(String.Format("ILP Max.: {0}", ilpElapsed));
Console.WriteLine();
normalElapsed = normal.Average(time => time.TotalMilliseconds);
Console.WriteLine(String.Format("Normal Avg.: {0}", normalElapsed));
ilpElapsed = ilp.Average(time => time.TotalMilliseconds);
Console.WriteLine(String.Format("ILP Avg.: {0}", ilpElapsed));
Console.WriteLine();
normalElapsed = normal.Min(time => time.TotalMilliseconds);
Console.WriteLine(String.Format("Normal Min.: {0}", normalElapsed));
ilpElapsed = ilp.Min(time => time.TotalMilliseconds);
Console.WriteLine(String.Format("ILP Min.: {0}", ilpElapsed));
}
Результаты (в .Net Framework 4.0 Профиль клиента, выпуск):
На виртуальной машине (я думаю, без ILP):
True True
Нор Макс .: 111,1894
НЛП Макс .: 106,886
Нор .: 78, 163619
ILP Avg .: 77,682513
Nor Min .: 58,3035
ILP Min .: 56,7672
на ксеноне :
True True
Nor Макс .: 40,5892
ILP Макс .: 30,8906
Nor Avg .: 35,637308
ILP Avg.: 25,45341
Nor Мин .: 34,4247
ILP Мин .: 23,7888
Объяснение результатов:
В Debug нетОптимизация применяется компилятором, но второй цикл for является более оптимальным, чем первый, поэтому существует существенная разница.
ThКажется, что ответ заключается в результатах выполнения сборок, собранных в режиме Release.Компилятор IL / JIT-er позволяют минимизировать снижение производительности (я думаю, даже ILP).Но если вы создаете код, подобный второму циклу for, вы можете достичь лучших результатов в особых случаях, и второй цикл может превзойти первый в некоторых архитектурах.Но
Вы находитесь во власти JIT
, как уже упоминалось, к сожалению.Грустная вещь, что нет упоминания о реализации, может определить больше оптимизации, как ILP (короткий параграф может быть помещен в спецификацию).Но они не могут перечислить все формы архитектурных вариантов кода, и CLI находится на более высоком уровне:
Это хорошо абстрагируется от языков .NET и IL.
Это очень сложная задача, ответить на нее только экспериментальным путем.Я не думаю, что мы могли бы получить гораздо более точный ответ таким образом.И я думаю, что Вопрос вводит в заблуждение, потому что это не зависит от C #, это зависит от реализации CLI.
Могло быть много влияющих факторов, и затрудняется правильно ответить на вопрос, подобный этому, думая оJIT, пока мы не воспринимаем его как «черный ящик».
На странице 512-513: http://www.ecma -international.org / публикации / файлы / ECMA-ST / ECMA я нашел информацию о векторизации и автопоточности-335.pdf
Я думаю, что они не указывают явно, как JIT-er должен вести себя в подобных случаях, и импелентеры могут выбрать способ оптимизации.Поэтому я думаю, что вы можете повлиять, если вы сможете написать более оптимальный код, и JIT попытается использовать ILP, если это возможно / реализовано.
Я думаю, потому что они не указывают, есть возможность.
Таким образом, ответ вроде бы Нет. Я полагаю, что вы не можете абстрагироваться от ILP в случае CLI, если в спецификации это не сказано.
Обновление :
Я уже нашел пост в блоге, но до сих пор его не нашел: http://igoro.com/archive/gallery-of-processor-cache-effects/ Пример четвертый содержит короткий, но правильный ответ на ваш вопрос.