Ваше решение не может работать. Поскольку A инициализируется в -1, а A[0][j]
никогда не изменяется, если i==1
, он будет проверять A[1-1][j]
и всегда будет терпеть неудачу. Кстати, если A инициализируется в -1, как у вас не может быть ничего кроме -1 с максимумом?
Когда у вас есть проблема зависимостей, есть два решения.
Первый - это упорядочить ваш код. Openmp имеет директиву ordered
для этого, но недостатком является то, что вы теряете параллелизм (при этом все равно оплачивая стоимость создания потока). В Openmp 4.5 есть способ описания зависимостей с помощью операторов зависимостей и приемника / источника, но я не знаю, насколько эффективным может быть компилятор, чтобы справиться с этим. А мои компиляторы (gcc 7.3 или clang 6.0) не поддерживают эту функцию.
Второе решение состоит в том, чтобы изменить ваш алгоритм на , подавить зависимости . Теперь вы вычисляете максимум всех значений, которые находятся слева или над данным элементом. Давайте обратимся к более простой проблеме. Вычислить максимум всех значений слева от данного элемента. Мы можем легко распараллелить его, вычисляя разные строки, поскольку нет зависимости между строками.
// compute b[i][j]=max_k<j(a[i][k]
#pragma omp parallel for
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
// max per row
if((j!=0)) b[i][j]=max(a[i][j],b[i][j-1]);
else b[i][j]=a[i][j]; // left column initialised to value of a
}
}
Рассмотрим еще одну простую задачу - вычислить максимум префикса для разных столбцов. Снова легко распараллелить, но на этот раз по внутреннему циклу, поскольку между столбцами нет зависимости.
// compute c[i][j]=max_i<k(b[k,j])
for(int i=0;i<n;i++){
#pragma omp parallel for
for(int j=0;j<n;j++){
// max per column
if((i!=0)) c[i][j]=max(b[i][j],c[i-1][j]);
else c[i][j]=b[i][j]; // upper row initialised to value of b
}
}
Теперь вам просто нужно объединить эти вычисления, чтобы получить ожидаемый результат. Вот окончательный код (с использованием уникального массива и некоторой очистки в коде).
#pragma omp parallel for
for(int i=0;i<n;i++){
for(int j=1;j<n;j++){
// max per row
a[i][j]=max(a[i][j],a[i][j-1]);
}
}
for(int i=1;i<n;i++){
#pragma omp parallel for
for(int j=0;j<n;j++){
// max per column
a[i][j]=max(a[i][j],a[i-1][j]);
}
}
Queue
имеет конструктор, который принимает в ICollection
. Вы можете передать свой список в очередь, чтобы инициализировать его теми же элементами:
var queue = new Queue<T>(list); // where 'T' is the lists data type.
Добавьте это расширение в свою панель инструментов, чтобы создать очередь FIFO определенного типа.
public static class ListExtensions
{
public static Queue<T> ToQueue<T>(this List<T> items) => new Queue<T>(items);
}
Что вы подразумеваете под «в том же порядке?»
Если вы сделаете это:
var queue = new Queue<object>(list);
Тогда очередь будет пронумерована в том же порядке, что и список, что означает, что вызов Dequeue
вернет элемент, который ранее находился в list [0]
.
Если вы сделаете следующее:
var queue = new Queue<object>(list.AsEnumerable().Reverse());
Тогда очередь будет пронумерована в порядке, обратном списку, что означает, что вызов Dequeue
вернет элемент, который ранее находился в ] список [list.Count - 1]
.
var q = new Queue<Object>();
for( int i = 0; i < list.Count; i++ ) q.Enqueue( list[i] );
То есть, предположение, что «такой же порядок» означает, что первым элементом, который должен быть исключен из очереди, должен быть список [0].
Если это означает обратное, просто используйте обратный цикл: for (int i = list.Count-1; i> = 0; i--)
var mylist = new List<int> {1,2,3};
var q = new Queue<int>(mylist);