Что такое забор памяти?

Spark 2.1 +

Вы можете использовать функцию from_json :

import org.apache.spark.sql.functions.from_json
import org.apache.spark.sql.types._

val schema = StructType(Seq(
  StructField("k", StringType, true), StructField("v", DoubleType, true)
))

df.withColumn("jsonData", from_json($"jsonData", schema))

Spark 1.6 +

Вы можете используйте get_json_object, который берет столбец и путь:

import org.apache.spark.sql.functions.get_json_object

val exprs = Seq("k", "v").map(
  c => get_json_object($"jsonData", s"$$.$c").alias(c))

df.select($"*" +: exprs: _*)

и извлекает поля для отдельных строк, которые могут быть добавлены к ожидаемым типам.

Аргумент path выраженный с использованием точечного синтаксиса, с ведущим $., обозначающим корень документа (поскольку используемый выше код использует интерполяцию строк $, поэтому $$.).

Spark & ​​lt; = 1.5:

Возможно ли это?

blockquote>

Насколько я знаю, это невозможно. Вы можете попробовать что-то похожее на это:

val df = sc.parallelize(Seq(
  ("1", """{"k": "foo", "v": 1.0}""", "some_other_field_1"),
  ("2", """{"k": "bar", "v": 3.0}""", "some_other_field_2")
)).toDF("key", "jsonData", "blobData")

Я предполагаю, что поле blob не может быть представлено в JSON. В противном случае вы откажитесь от разделения и соединения:

import org.apache.spark.sql.Row

val blobs = df.drop("jsonData").withColumnRenamed("key", "bkey")
val jsons = sqlContext.read.json(df.drop("blobData").map{
  case Row(key: String, json: String) =>
    s"""{"key": "$key", "jsonData": $json}"""
}) 

val parsed = jsons.join(blobs, $"key" === $"bkey").drop("bkey")
parsed.printSchema

// root
//  |-- jsonData: struct (nullable = true)
//  |    |-- k: string (nullable = true)
//  |    |-- v: double (nullable = true)
//  |-- key: long (nullable = true)
//  |-- blobData: string (nullable = true)

Альтернативный (более дешевый, хотя и более сложный) подход - использовать UDF для разбора JSON и вывода столбца struct или map. Например, что-то вроде этого:

import net.liftweb.json.parse

case class KV(k: String, v: Int)

val parseJson = udf((s: String) => {
  implicit val formats = net.liftweb.json.DefaultFormats
  parse(s).extract[KV]
})

val parsed = df.withColumn("parsedJSON", parseJson($"jsonData"))
parsed.show

// +---+--------------------+------------------+----------+
// |key|            jsonData|          blobData|parsedJSON|
// +---+--------------------+------------------+----------+
// |  1|{"k": "foo", "v":...|some_other_field_1|   [foo,1]|
// |  2|{"k": "bar", "v":...|some_other_field_2|   [bar,3]|
// +---+--------------------+------------------+----------+

parsed.printSchema

// root
//  |-- key: string (nullable = true)
//  |-- jsonData: string (nullable = true)
//  |-- blobData: string (nullable = true)
//  |-- parsedJSON: struct (nullable = true)
//  |    |-- k: string (nullable = true)
//  |    |-- v: integer (nullable = false)

106
задан Daniel Rikowski 6 May 2009 в 07:28
поделиться

4 ответа

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

забор/барьер памяти А является классом инструкций, что среднее чтение-записи памяти происходит в порядке, который Вы ожидаете. Например, 'весь забор' означает все чтение-записи, прежде чем забор будет фиксироваться перед теми после забора.

заборы памяти Примечания являются аппаратным понятием. На высокоуровневых языках мы привыкли иметь дело со взаимными исключениями и семафорами - они могут быть реализованы с помощью заборов памяти на низком уровне, и конкретный вид использования барьеров памяти не необходимы. Использование барьеров памяти требует тщательного исследования аппаратной архитектуры и чаще всего находимый в драйверах устройств, чем код приложения.

переупорядочение ЦП отличается от оптимизаций компилятора - хотя артефакты могут быть подобными. Необходимо принять отдельные меры для остановки компилятора, переупорядочивающего инструкции, если это может вызвать нежелательное поведение (например, использование энергозависимого ключевого слова в C).

100
ответ дан Kirill Kobelev 5 November 2019 в 10:49
поделиться

Копирование мой ответ к другому вопросу, , Каковы некоторые приемы, которые процессор делает для оптимизации кода? :

самый важный был бы переупорядочением доступа к памяти.

Отсутствующие заборы памяти или инструкции по сериализации, процессор свободен переупорядочить доступы памяти. Некоторые архитектуры процессора имеют ограничения на то, сколько они могут переупорядочить; Альфа известна тем, что она была самой слабой (т.е. тот, который может переупорядочить большинство).

А очень хорошая обработка предмета может быть найдена в исходной документации ядра Linux, в Documentation/memory-barriers.txt .

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

15
ответ дан Community 5 November 2019 в 10:49
поделиться

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

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

А хорошее введение в проблему" , 'Перепроверяемая Блокировка Повреждается' Объявление ". Для многих это был призыв к действию это там быть драконами.

Неявные полные барьеры памяти обычно включаются в стандартные программы синхронизации потока платформы, которые покрывают ядро его. Однако для программирования без блокировок и реализации пользовательских, легких шаблонов синхронизации, Вам часто нужен просто барьер, или даже односторонний барьер только.

6
ответ дан Alexander 5 November 2019 в 10:49
поделиться

Википедия знает все...

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

центральные процессоры используют оптимизацию производительности, которая может привести к выполнению с изменением последовательности, включая загрузку в память и сохранить операции. Операция памяти, переупорядочивающая обычно, остается незамеченной в единственном потоке выполнения, но вызывает непредсказуемое поведение в параллельных программах и драйверах устройств, если тщательно не управляется. Точный характер ограничения упорядочивания аппаратно-зависим, и определенный моделью памяти архитектуры. Некоторая архитектура обеспечивает несколько барьеров для осуществления различных ограничений упорядочивания.

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

1
ответ дан Omar Kooheji 5 November 2019 в 10:49
поделиться
Другие вопросы по тегам:

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