Форум программистов, компьютерный форум, киберфорум
Go (Golang)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141

Записать []uint32 в файл

20.02.2023, 01:18. Показов 1309. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер. Подскажите пожалуйста. Go lang изучаю только неделю и не получается разобраться.
Есть массив uint32 на более чем 100млн элементов, необходимо записать в файл, и при запуске программы загрузить его в оперативную память.
На python данную задачу решил с помощью библиотеки pickle. На загрузку файла в память уходит всего 6.5 сотых секунды.
Те решения что нашел в гугле к сожалению совсем не помогли.((

Добавлено через 2 часа 21 минуту
Пока вот так сделал. Лютый колхоз, на создание массива уходит почти секунда((
Слишком долго. И файл весит 522 мб. А pickle 261 мб

Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main
 
import (
    "encoding/binary"
    "fmt"
    "log"
    "math/rand"
    "os"
    "time"
)
 
func doByteFromUint32(h uint32) []byte {
    a := make([]byte, 4)
    binary.LittleEndian.PutUint32(a, h)
    return a
}
 
func readFile() []uint32 {
    var mySlice []uint32
    arr2, _ := os.ReadFile("file2.txt")
    for i := 0; i < len(arr2); i += 4 {
        mySlice = append(mySlice, binary.LittleEndian.Uint32(arr2[i:i+4]))
    }
    return mySlice
}
func createArr() {
    arr3 := sqlTry()
    f, err := os.OpenFile("file2.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        log.Fatal(err)
    }
    rand.Seed(time.Now().Unix())
    for i := 0; i < len(arr3); i++ {
        f.Write(doByteFromUint32(arr3[i]))
    }
}
1
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.02.2023, 01:18
Ответы с готовыми решениями:

Создать текстовый файл, записать туда информацию. прочесть, серилизовать и записать байтовый поток в другой файл
Привет....помогите пожалуйста, очень надо...и очень срочно. несколько заданий по яве: 1. создать текстовый файл, записать туда...

Сформировать текстовый файл записать в него 20 случайных чисел от-10 до 10 по 1 на строку записать выходной файл умножив
День добрый. Убил день но так и не смог сделать задание так или иначе делаю но получается херня если не сложно прошу помочь решением...

Создать структуру из двух строковых полей. Записать в файл n компонент типа этой структуры. В другой файл записать строк
Бинарные файлы. Создать структуру из двух строковых полей. Записать в файл n компонент типа этой структуры. В другой файл записать строки,...

17
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
20.02.2023, 09:02
Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
И файл весит 522 мб. А pickle 261 мб
Потому что нужно O_TRUNC, а не O_APPEND.

Go
1
2
3
4
5
6
7
8
9
10
11
12
13
func readFile() []uint32 {
    var data, err = os.ReadFile(file)
    if err != nil {
        log.Fatal(err)
    }
 
    var nums = make([]uint32, 0, len(data)/4)
 
    for i := 0; i < len(data); i += 4 {
        nums = append(nums, binary.LittleEndian.Uint32(data[i:i+4]))
    }
    return nums
}
0
366 / 330 / 83
Регистрация: 17.04.2022
Сообщений: 1,086
Записей в блоге: 8
20.02.2023, 09:10
Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
И файл весит 522 мб.
в вашем коде не видно что такое sqlTry(). так что по поводу 522 - разберитесь с sqlTry()

Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
А pickle 261 мб
100млн * 4 = 400 млн байтов. как-то не похоже на 261мб
0
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141
20.02.2023, 10:20  [ТС]
korvin_, Спасибо, Ваш вариант выполняется в 2 раза быстрее, за 0.5 секунды. А если по индексу добавлять то 0.4 сек. Что все равно очень долго...(
Go
1
2
3
4
5
6
7
8
9
10
11
12
13
func readFile() []uint32 {
    var data, err = os.ReadFile("newfolder/byteArr.txt")
    if err != nil {
        log.Fatal(err)
    }
    var nums = make([]uint32, 0, len(data)/4)
    x := 0
    for i := 0; i < len(data); i += 4 {
        nums[x] = binary.LittleEndian.Uint32(data[i : i+4])
        x++
    }
    return nums
}
0
366 / 330 / 83
Регистрация: 17.04.2022
Сообщений: 1,086
Записей в блоге: 8
20.02.2023, 11:38
Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
Есть массив uint32 на более чем 100млн элементов, необходимо записать в файл, и при запуске программы загрузить его в оперативную память.
На python данную задачу решил с помощью библиотеки pickle. На загрузку файла в память уходит всего 6.5 сотых секунды.
100млн * 4байта /0.065 сек = 6153 млн.байт/сек

не поделитесь информацией о hardware?

я подозреваю, что pickle после записи сохраняет данные в памяти и поэтому когда вы их повторно загружаете, вам отдают их из памяти.

попробуйте провести "чистый" тест с python версией, когда вы будете только читать файл с диска.
0
Модератор
 Аватар для Curry
5158 / 3482 / 536
Регистрация: 01.06.2013
Сообщений: 7,549
Записей в блоге: 9
20.02.2023, 12:16
А так не быстрее будет?
Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import (
    "encoding/binary"
    "bufio"
    "fmt"
    "os"
)
 
func readFile(filename string) ([]uint32,error) {
    file, err := os.Open(filename)
 
    if err != nil {
        return nil, err
    }
    defer file.Close()
 
    stats, err := file.Stat()
    if err != nil {
        return nil, err
    }
 
    var size int64 = stats.Size()/4
    mySlice := make([]uint32, size)
 
    rdr := bufio.NewReader(file)
    err = binary.Read(rdr, binary.LittleEndian, mySlice)
    return mySlice,err
}
Я в go не специалист, так, посматриваю на него.
Так что это действительно вопрос, код проверил на https://go.dev/play/ но на скорость не тестировал.
0
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141
20.02.2023, 14:13  [ТС]
Curry, Спасибо за участие, но к сожалению примерно на 60% медленнее. 0.66 sec vs 0.41.

Добавлено через 9 минут
sqltd1, Извиняюсь, обманул, массив был сохранен как uint16.
На массиве numpy array uint32, состоящем из 134млн элементов, импортированным в pickle файл на чтение затрачивается 0.141344 sec. Вес файла 522 мегабайта.
ryzen 3960x, Samsung 960 pro, DDDR 4 32gb, 2933Мгц
0
366 / 330 / 83
Регистрация: 17.04.2022
Сообщений: 1,086
Записей в блоге: 8
20.02.2023, 14:39
Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
На массиве numpy array uint32, состоящем из 134млн элементов, импортированным в pickle файл на чтение затрачивается 0.141344 sec. Вес файла 522 мегабайта.
итого зафиксирована скорость чтения 522mb/0.141344 sec = 3700mb/sec

как-то не совпадает с цифрами на https://www.notebookcheck.net/... 694.0.html

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

может приведете код на python, который вам дает эти значения?
1
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141
20.02.2023, 15:32  [ТС]
sqltd1,
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import os
import time
import pickle
 
 
if __name__ == '__main__':
    t1_start = time.perf_counter()
    with open('numpy_arr_32.pkl', 'rb') as fp:
        all_dict = pickle.load(fp)
    print(f'На чтение файла ушло {round(time.perf_counter() - t1_start, 6)} sec')
    print(f'{len(all_dict) = }')
    print(f'{type(all_dict) = }')
    print(f'{type(all_dict[1000000]) = }')
    print(f'{os.path.getsize("numpy_arr_32.pkl") = }')
На чтение файла ушло 0.147652 sec
len(all_dict) = 133784560
type(all_dict) = <class 'numpy.ndarray'>
type(all_dict[1000000]) = <class 'numpy.uint32'>
os.path.getsize("numpy_arr_32.pkl") = 535138402

Process finished with exit code 0
0
Модератор
 Аватар для Curry
5158 / 3482 / 536
Регистрация: 01.06.2013
Сообщений: 7,549
Записей в блоге: 9
20.02.2023, 15:55
Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
На чтение файла ушло 0.147652 sec
А на go вы как время замеряете? Может туда попадает время загрузки программы или ещё что.
0
366 / 330 / 83
Регистрация: 17.04.2022
Сообщений: 1,086
Записей в блоге: 8
20.02.2023, 16:02
Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
На чтение файла ушло 0.147652 sec
хм.хм. интересно. насчет чтения давайте проверим. чтение может быть "ленивым"

предлагаю вставить код суммирования всех элементов массива. и сделать еще одну засечку времени после исполнения этого кода. это позволит утверждать, что у вас действительно все элементы массива были прочитаны.
0
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141
20.02.2023, 16:47  [ТС]
sqltd1, Так тяжело понять.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import os
import random
import time
import pickle
import numpy as np
 
if __name__ == '__main__':
    t1_start = time.perf_counter()
    with open('numpy_arr_32.pkl', 'rb') as fp:
        all_dict = pickle.load(fp)
    print(f'На чтение файла ушло {round(time.perf_counter() - t1_start, 6)} sec')
    print(f'{len(all_dict) = }')
    print(f'{type(all_dict) = }')
    print(f'{type(all_dict[1000000]) = }')
    print(f'{os.path.getsize("numpy_arr_32.pkl") = }')
    t1_start = time.perf_counter()
    print(f'{sum(all_dict) = }')
    print(f'На получение суммы всего массива {round(time.perf_counter() - t1_start, 6)} sec')
 
    all_dict2 = np.zeros(133784560, dtype=np.uint32)
    for i in range(len(all_dict)):
        all_dict2[i] = random.randint(1, 75000)
    t1_start = time.perf_counter()
    print(f'{sum(all_dict2) = }')
    print(f'На получение суммы всего массива 2 {round(time.perf_counter() - t1_start, 6)} sec')


На чтение файла ушло 0.170723 sec
len(all_dict) = 133784560
type(all_dict) = <class 'numpy.ndarray'>
type(all_dict[1000000]) = <class 'numpy.uint32'>
os.path.getsize("numpy_arr_32.pkl") = 535138402
sum(all_dict) = 5017300213960
На получение суммы всего массива 17.200826 sec
sum(all_dict2) = 5016806058186
На получение суммы всего массива 2 16.667877 sec

Process finished with exit code 0

Добавлено через 13 минут
max(all_dict) = 75000
На получение максимума всего массива 6.511391 sec
max(all_dict2) = 75000
На получение максимума всего массива 2 6.6312 sec
0
366 / 330 / 83
Регистрация: 17.04.2022
Сообщений: 1,086
Записей в блоге: 8
20.02.2023, 16:49
Спасибо.

Мда. Python, однако, тормозной.

Тем не менее - время на sum(all_dict) на 0.5сек больше, чем время на sum(all_dict2).
С высокой долей вероятности это свидетельствует о том, что pickle.load реализует "ленивую" загрузку и реальное время должно быть примерно на 0.5 сек больше. И вы приблизились к значению, которое демонстрирует го.

для полноты картины, - ос кеширует файловые операции, поэтому для получения более или менее объективных цифр нужно принудительно сбрасывать кеш ос между тестами. (например, самое простое, - копирование массивных файлов)
0
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141
20.02.2023, 18:09  [ТС]
sqltd1, Не соглашусь. Воспользовался встроенной функцией numpy на получение суммы, перед этим перезагрузил пк.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import os
import random
import time
import pickle
import numpy as np
 
if __name__ == '__main__':
    t1_start = time.perf_counter()
    with open('numpy_arr_32.pkl', 'rb') as fp:
        all_dict = pickle.load(fp)
    print(f'На чтение файла ушло {round(time.perf_counter() - t1_start, 6)} sec')
    print(f'{len(all_dict) = }')
    print(f'{type(all_dict) = }')
    print(f'{type(all_dict[1000000]) = }')
    print(f'{os.path.getsize("numpy_arr_32.pkl") = }')
    t1_start = time.perf_counter()
    print(f'{np.sum(all_dict) = }')
    print(f'На получение суммы всего массива {round(time.perf_counter() - t1_start, 6)} sec')
 
    all_dict2 = np.zeros(133784560, dtype=np.uint32)
    for i in range(len(all_dict)):
        all_dict2[i] = random.randint(1, 75000)
    t1_start = time.perf_counter()
    print(f'{np.sum(all_dict2) = }')
    print(f'На получение суммы всего массива 2 {round(time.perf_counter() - t1_start, 6)} sec')
На чтение файла ушло 0.338112 sec
len(all_dict) = 133784560
type(all_dict) = <class 'numpy.ndarray'>
type(all_dict[1000000]) = <class 'numpy.uint32'>
os.path.getsize("numpy_arr_32.pkl") = 535138402
np.sum(all_dict) = 778412232
На получение суммы всего массива = 0.040005 sec
np.sum(all_dict2) = 249578910
На получение суммы всего массива 2 = 0.035714 sec

Время подсчета суммы первого массива варьируется от 0,035-0,04

Добавлено через 8 минут
Curry,
Go
1
2
3
4
5
6
7
8
9
10
11
func readFile() []uint16 {
    start2 := time.Now()
    var data, _ = os.ReadFile("new.txt")
    var nums = make([]uint16, 0, 133784560)
    for i := 0; i < 267569120; i += 2 {
        nums = append(nums, binary.LittleEndian.Uint16(data[i:i+2]))
    }
    duration2 := time.Since(start2)
    fmt.Println(duration2)
    return nums
}
0
366 / 330 / 83
Регистрация: 17.04.2022
Сообщений: 1,086
Записей в блоге: 8
20.02.2023, 18:18
Цитата Сообщение от vpip75pfr3 Посмотреть сообщение
На чтение файла ушло 0.338112 sec
вас не смущает такой разброс?

а так из интересных вещей - было-бы более информативно получать продолжительность всех интервалов

что-нибудь типа такого

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import os
import random
import time
import pickle
import numpy as np
 
if __name__ == '__main__':
    t1_start = time.perf_counter()
    with open('numpy_arr_32.pkl', 'rb') as fp:
        all_dict = pickle.load(fp)
    t2 = time.perf_counter()
    print(f'На чтение файла ушло {round(t2 - t1_start, 6)} sec')
    print(f'{len(all_dict) = }')
    print(f'{type(all_dict) = }')
    print(f'{type(all_dict[1000000]) = }')
    t3 = time.perf_counter()
    print(f'На чтение файла-2 ушло {round(t3 - t2, 6)} sec')
    print(f'{os.path.getsize("numpy_arr_32.pkl") = }')
    t4 = time.perf_counter()
    print(f'{np.sum(all_dict) = }')
    t5 = time.perf_counter()
    print(f'На получение суммы всего массива {round(t5 - t4, 6)} sec')
 
    all_dict2 = np.zeros(133784560, dtype=np.uint32)
    for i in range(len(all_dict)):
        all_dict2[i] = random.randint(1, 75000)
    t1_start = time.perf_counter()
    print(f'{np.sum(all_dict2) = }')
    print(f'На получение суммы всего массива 2 {round(time.perf_counter() - t1_start, 6)} sec')
0
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141
20.02.2023, 18:28  [ТС]
sqltd1,
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import os
import time
import pickle
import numpy as np
 
if __name__ == '__main__':
    t1_start = time.perf_counter()
    with open('numpy_arr_32.pkl', 'rb') as fp:
        all_dict = pickle.load(fp)
    t2 = time.perf_counter()
    print(f'На чтение файла ушло {round(t2 - t1_start, 6)} sec')
    print(f'{len(all_dict) = }')
    print(f'{type(all_dict) = }')
    print(f'{type(all_dict[1000000]) = }')
    t3 = time.perf_counter()
    print(f'На чтение файла-2 ушло {round(t3 - t2, 6)} sec')
    print(f'{os.path.getsize("numpy_arr_32.pkl") = }')
    t4 = time.perf_counter()
    print(f'{np.sum(all_dict) = }')
    t5 = time.perf_counter()
    print(f'На получение суммы всего массива {round(t5 - t4, 6)} sec')
 
    all_dict2 = np.random.randint(75000, size=133784560, dtype=np.uint32)
    t1_start = time.perf_counter()
    print(f'{np.sum(all_dict2) = }')
    t6 = time.perf_counter()
    print(f'На получение суммы всего массива 2 {round(t6 - t1_start, 6)} sec')
На чтение файла ушло 0.127258 sec
len(all_dict) = 133784560
type(all_dict) = <class 'numpy.ndarray'>
type(all_dict[1000000]) = <class 'numpy.uint32'>
На чтение файла-2 ушло 4.9e-05 sec
os.path.getsize("numpy_arr_32.pkl") = 535138402
np.sum(all_dict) = 778412232
На получение суммы всего массива 0.036327 sec
np.sum(all_dict2) = 144475437
На получение суммы всего массива 2 0.036797 sec

Добавлено через 6 минут
Сразу после перезагрузки время на первое чтение файла примерно в 3 раза превышает все последующие.
0
366 / 330 / 83
Регистрация: 17.04.2022
Сообщений: 1,086
Записей в блоге: 8
20.02.2023, 18:39
Пара вопросов

А вы Python перезапускаете между тестами?

Озвучьте результаты "скорости чтения файлов" (только не скорость последовательного чтения секторов) какого-нибудь приложения для оценки параметров диска. Просто, что бы было ясно к чему мы стремимся
0
6 / 2 / 0
Регистрация: 28.06.2019
Сообщений: 141
20.02.2023, 19:00  [ТС]
sqltd1, только ребут помогает кеш удалить.
Да по итогу скорость первого чтения около 0.35 sec. Что близко к значению GO, думаю GO тратит больше времени на создание slice, поэтому чуть проигрывает.
Сейчас я запускаю функцию go скомпилировав ее в dll, через python.
Было бы круто если бы можно было 1 раз запустить функцию создания массива, а потом запускать функцию которая использует этот массив. Но я понятия не имею как это можно сделать.
Миниатюры
Записать []uint32 в файл  
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.02.2023, 19:00
Помогаю со студенческими работами здесь

Создать структуру из двух строковых полей. Записать в файл n компонент типа этой структуры. В другой файл записать строк
бинарные файлы.Создать структуру из двух строковых полей. Записать в файл n компонент типа этой структуры. В другой файл записать строки,...

В файл записать 10 чисел. Создать новый файл, в который записать только четные числа.
В файл записать 10 чисел. Создать новый файл, в который записать только четные числа.

Надо записать в файл, считать из файла, и снова записать в отдельный файл
Надо сделать так, чтобы я ввел n, и это количество элементов запишется в файл input.txt, и потом производится считывание массива из только...

нужно зашифровать текст в файле с помощю чисел, записать шифр в другой файл, потом разшифровать и записать разшифрованый текст в третий файл
нужно зашифровать текст в файле с помощю чисел, записать шифр в другой файл, потом разшифровать и записать разшифрованый текст в третий файл

Два числа записать в файл input, сравнить эти числа и если A < B записать в файл Output этот знак
Решаю такую задачу: нужно два числа записать в файл input потом сравнить эти числа, и если A &lt; B записать в файл Output этот знак. Часть...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru