112 lines
2.8 KiB
Go
112 lines
2.8 KiB
Go
package randomx
|
|
|
|
import (
|
|
"errors"
|
|
"git.gammaspectra.live/P2Pool/go-randomx/v3/internal/memory"
|
|
"sync"
|
|
)
|
|
|
|
const DatasetSize = RANDOMX_DATASET_BASE_SIZE + RANDOMX_DATASET_EXTRA_SIZE
|
|
|
|
const DatasetItemCount = DatasetSize / CacheLineSize
|
|
|
|
type Dataset struct {
|
|
memory []RegisterLine
|
|
flags Flags
|
|
}
|
|
|
|
// NewDataset Creates a randomx_dataset structure and allocates memory for RandomX Dataset.
|
|
// Only one flag is supported (can be set or not set): RANDOMX_FLAG_LARGE_PAGES - allocate memory in large pages
|
|
// Returns nil if allocation fails
|
|
func NewDataset(flags Flags) (result *Dataset, err error) {
|
|
defer func() {
|
|
//catch too large memory allocation or unable to allocate, for example on 32-bit targets or out of memory
|
|
if r := recover(); r != nil {
|
|
result = nil
|
|
if e, ok := r.(error); ok && e != nil {
|
|
err = e
|
|
} else {
|
|
err = errors.New("out of memory")
|
|
}
|
|
}
|
|
}()
|
|
|
|
var alignedMemory []RegisterLine
|
|
|
|
if flags.Has(RANDOMX_FLAG_LARGE_PAGES) {
|
|
if largePageAllocator == nil {
|
|
return nil, errors.New("huge pages not supported")
|
|
}
|
|
alignedMemory, err = memory.AllocateSlice[RegisterLine](largePageAllocator, DatasetItemCount)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
alignedMemory, err = memory.AllocateSlice[RegisterLine](cacheLineAlignedAllocator, DatasetItemCount)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &Dataset{
|
|
memory: alignedMemory,
|
|
flags: flags,
|
|
}, nil
|
|
}
|
|
|
|
func (d *Dataset) prefetchDataset(address uint64) {
|
|
|
|
}
|
|
|
|
func (d *Dataset) readDataset(address uint64, r *RegisterLine) {
|
|
cache := &d.memory[address/CacheLineSize]
|
|
|
|
for i := range r {
|
|
r[i] ^= cache[i]
|
|
}
|
|
}
|
|
|
|
// Memory Returns a pointer to the internal memory buffer of the dataset structure.
|
|
// The size of the internal memory buffer is DatasetItemCount * RANDOMX_DATASET_ITEM_SIZE.
|
|
func (d *Dataset) Memory() []RegisterLine {
|
|
return d.memory
|
|
}
|
|
|
|
func (d *Dataset) InitDataset(cache *Cache, startItem, itemCount uint64) {
|
|
if startItem >= DatasetItemCount || itemCount > DatasetItemCount {
|
|
panic("out of range")
|
|
}
|
|
if startItem+itemCount > DatasetItemCount {
|
|
panic("out of range")
|
|
}
|
|
cache.datasetInit(d.memory[startItem:startItem+itemCount], startItem, startItem+itemCount)
|
|
}
|
|
|
|
func (d *Dataset) Close() error {
|
|
if d.flags.Has(RANDOMX_FLAG_LARGE_PAGES) {
|
|
return memory.FreeSlice(largePageAllocator, d.memory)
|
|
} else {
|
|
return memory.FreeSlice(cacheLineAlignedAllocator, d.memory)
|
|
}
|
|
}
|
|
|
|
func (d *Dataset) InitDatasetParallel(cache *Cache, n int) {
|
|
n = max(1, n)
|
|
|
|
var wg sync.WaitGroup
|
|
for i := uint64(1); i < uint64(n); i++ {
|
|
a := (DatasetItemCount * i) / uint64(n)
|
|
b := (DatasetItemCount * (i + 1)) / uint64(n)
|
|
|
|
wg.Add(1)
|
|
go func(a, b uint64) {
|
|
defer wg.Done()
|
|
d.InitDataset(cache, a, b-a)
|
|
}(a, b)
|
|
}
|
|
|
|
d.InitDataset(cache, 0, DatasetItemCount/uint64(n))
|
|
wg.Wait()
|
|
}
|