Макро-векторное умножение OpenMP на лету в Fortran [дубликат]

Может работать с бесконечными генераторами:

a.Zip(a.Skip(1), (x, y) => Enumerable.Repeat(x, 1).Concat(Enumerable.Repeat(y, 1)))
 .Zip(a.Skip(2), (xy, z) => xy.Concat(Enumerable.Repeat(z, 1)))
 .Where((x, i) => i % 3 == 0)

Демо-код: https://ideone.com/GKmL7M

using System;
using System.Collections.Generic;
using System.Linq;

public class Test
{
  private static void DoIt(IEnumerable a)
  {
    Console.WriteLine(String.Join(" ", a));

    foreach (var x in a.Zip(a.Skip(1), (x, y) => Enumerable.Repeat(x, 1).Concat(Enumerable.Repeat(y, 1))).Zip(a.Skip(2), (xy, z) => xy.Concat(Enumerable.Repeat(z, 1))).Where((x, i) => i % 3 == 0))
      Console.WriteLine(String.Join(" ", x));

    Console.WriteLine();
  }

  public static void Main()
  {
    DoIt(new int[] {1});
    DoIt(new int[] {1, 2});
    DoIt(new int[] {1, 2, 3});
    DoIt(new int[] {1, 2, 3, 4});
    DoIt(new int[] {1, 2, 3, 4, 5});
    DoIt(new int[] {1, 2, 3, 4, 5, 6});
  }
}
1

1 2

1 2 3
1 2 3

1 2 3 4
1 2 3

1 2 3 4 5
1 2 3

1 2 3 4 5 6
1 2 3
4 5 6

Но на самом деле я бы предпочел написать соответствующий метод без linq.

53
задан SaiyanGirl 9 March 2013 в 00:59
поделиться

2 ответа

private переменные не инициализируются, то есть они начинаются со случайных значений, как любая другая локальная автоматическая переменная (и они часто реализуются с использованием автоматических переменных в стеке каждого потока). Возьмите эту простую программу в качестве примера:

#include <stdio.h>
#include <omp.h>

int main (void)
{
    int i = 10;

    #pragma omp parallel private(i)
    {
        printf("thread %d: i = %d\n", omp_get_thread_num(), i);
        i = 1000 + omp_get_thread_num();
    }

    printf("i = %d\n", i);

    return 0;
}

С четырьмя потоками она выводит что-то вроде:

thread 0: i = 0
thread 3: i = 32717
thread 1: i = 32717
thread 2: i = 1
i = 10

(another run of the same program)

thread 2: i = 1
thread 1: i = 1
thread 0: i = 0
thread 3: i = 32657
i = 10

Это наглядно демонстрирует, что значение i является случайным (не инициализируется) внутри параллельной области и что любые изменения в ней не видны после параллельной области (т. е. переменная сохраняет свое значение до входа в область).

Если i сделано firstprivate то он инициализируется значением, которое оно имеет перед параллельной областью:

thread 2: i = 10
thread 0: i = 10
thread 3: i = 10
thread 1: i = 10
i = 10

После него не видны изменения значения i внутри параллельной области.

Вы уже знаете о lastprivate (и он не применим к простой демонстрационной программе, поскольку он не имеет конструкций для совместной работы).

Итак, да, firstprivate и lastprivate являются только особыми случаями private. Первый результат приводит к тому, что значения из внешнего контекста приводятся в параллельный регион, а второй переносит значения из параллельной области во внешний контекст. Обоснованием этих классов совместного использования данных является то, что внутри параллельной области все частные переменные затеняют их из внешнего контекста, т. Е. Невозможно использовать операцию присваивания для изменения внешнего значения i изнутри параллельной области.

110
ответ дан Hristo Iliev 20 August 2018 в 23:06
поделиться
  • 1
    Это отличный ответ! Большое спасибо! – SaiyanGirl 11 March 2013 в 18:29
  • 2
    Ну, я бы сказал, firstprivate и lastprivate ОЧЕНЬ особые случаи private. Обычно вам даже не нужно использовать private (просто определите переменную внутри параллельного блока), возможно, затеняя внешнюю область. Интересным является использование объектов C ++ в качестве автоматических переменных firstprivate - они будут инициализированы путем создания копии, один раз и уничтожены после блока, и вам не нужно знать количество потоков заранее - так как многие копии будут при необходимости создаваться. – Tomasz Gandor 18 September 2014 в 08:26
  • 3
    Такой отличный пример! Нравится это больше всего. Цените Христо. – Fusionmate 2 March 2015 в 08:55
  • 4

firstprivate и lastprivate являются лишь частными случаями private.

Первое приводит к тому, что значения из внешнего контекста приводятся в параллельную область, а вторая передает значения из параллельной области во внешний контекст.

1
ответ дан J. Chomel 20 August 2018 в 23:06
поделиться
  • 1
    можете ли вы предоставить какие-либо справки об этом? – J. Chomel 20 January 2017 в 11:41
Другие вопросы по тегам:

Похожие вопросы: