Как добавить индикатор выполнения в третий цикл, показанный ниже?
Экспериментальные данные показали, что из следующих трех циклов третий является самым быстрым.Наилучшая производительность достигается, когда число потоков совпадает с логическими процессорами ЦП.Я думаю, что это связано с уменьшением времени, затрачиваемого на выделение и освобождение ресурсов потоков.
Это код для создания карты шума.Иногда время обработки достаточно велико, чтобы потребовался индикатор выполнения.
for (int j = 0; j < data.Length; j++)
{
var x = (location.X + (j % width));
var y = (location.Y + (j / width));
Vector3 p = new Vector3(x, y, frame);
p *= zoom;
float val = noise.GetNoise(p);
data[j] += val;
min = Math.Min(min, val);
max = Math.Max(max, val);
}
Parallel.For(0, data.Length, (i) => {
var x = (location.X + (i % width));
var y = (location.Y + (i / width));
Vector3 p = new Vector3(x, y, frame);
p *= zoom;
float val = noise.GetNoise(p);
data[i] += val;
min = Math.Min(min, val);
max = Math.Max(max, val);
});
Parallel.For(0, threads, (i) =>
{
int from = i * data.Length / threads;
int to = from + data.Length / threads;
if (i == threads - 1) to = data.Length - 1;
for (int j = from; j < to; j++)
{
var x = (location.X + (j % width));
var y = (location.Y + (j / width));
Vector3 p = new Vector3(x, y, frame);
p *= zoom;
float val = noise.GetNoise(p);
data[j] += val;
min = Math.Min(min, val);
max = Math.Max(max, val);
}
}
);
Индикатор выполнения, скорость обновления которого ограничена до нескольких раз в секунду, чтобы не тратить время на слишком частое рисование индикатора выполнения.будет лучшим.
Добавление IProgress Я прибыл сюда, и это почти работает.Проблема в том, что индикатор выполнения обновляется после того, как параллельный.for полностью завершен.
private async Task<int> FillDataParallelAsync(int threads, IProgress<int> progress)
{
int precent = 0;
/// parallel loop - easy and fast.
Parallel.For(0, threads, (i) =>
{
int from = i * data.Length / threads;
int to = from + data.Length / threads;
if (i == threads - 1) to = data.Length - 1;
for (int j = from; j < to; j++)
{
var x = (location.X + (j % width));
var y = (location.Y + (j / width));
Vector3 p = new Vector3(x, y, frame);
p *= zoom;
float val = noise.GetNoise(p);
data[j] += val;
min = Math.Min(min, val);
max = Math.Max(max, val);
if(j%(data.Length / 100) ==0)
{
if (progress != null)
{
progress.Report(precent);
}
Interlocked.Increment(ref precent);
}
}
}
);
return 0;
}
После слишком долгой работы над ним это выглядит так.
private Boolean FillDataParallel3D(int threads, CancellationToken token, IProgress<int> progress)
{
int precent = 0;
Vector3 imageCenter = location;
imageCenter.X -= width / 2;
imageCenter.Y -= height / 2;
ParallelOptions options = new ParallelOptions { CancellationToken = token };
/// parallel loop - easy and fast.
try
{
ParallelLoopResult result =
Parallel.For(0, threads, options, (i, loopState) =>
{
int from = i * data.Length / threads;
int to = from + data.Length / threads;
if (i == threads - 1) to = data.Length - 1;
for (int j = from; j < to; j++)
{
if (loopState.ShouldExitCurrentIteration) break;
Vector3 p = imageCenter;
p.X += (j % width);
p.Y += (j / width);
p *= zoom;
float val = noise.GetNoise(p);
data[j] += val;
min = Math.Min(min, val);
max = Math.Max(max, val);
if (j % (data.Length / 100) == 0)
{
try { if (progress != null) progress.Report(precent); }
catch { }
Interlocked.Increment(ref precent);
}
}
}
);
return result.IsCompleted;
}
catch { }
return false;
}
Прогрессчастично увеличивается от каждого потока до 100 раз.Он все еще имеет некоторую задержку при обновлении индикатора выполнения, но это кажется неизбежным.Например, если индикатор выполнения увеличивается в 100 раз меньше, чем время для вывода 100 обновлений, прогресс, похоже, выстраивается в очередь и продолжает прогрессировать после возврата метода.Подавление отображения прогресса на секунду после вызова метода работает достаточно хорошо.Индикатор выполнения действительно полезен только тогда, когда метод занимает так много времени, что вы задаетесь вопросом, если что-то происходит.
Полный проект на https://github.com/David-Marsh/Designer