Skip to content
This repository was archived by the owner on Apr 24, 2022. It is now read-only.

Commit c6dfc55

Browse files
authoredJul 29, 2020
Merge pull request #1998 from jean-m-cyr/master
Extend the life of 4GB cards
2 parents ff13d48 + 1457bf7 commit c6dfc55

File tree

2 files changed

+60
-19
lines changed

2 files changed

+60
-19
lines changed
 

‎libethash-cl/CLMiner.cpp

+27-5
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ bool CLMiner::initDevice()
708708
bool CLMiner::initEpoch_internal()
709709
{
710710
auto startInit = std::chrono::steady_clock::now();
711-
size_t RequiredMemory = (m_epochContext.dagSize + m_epochContext.lightSize);
711+
size_t RequiredMemory = (m_epochContext.dagSize);
712712

713713
// Release the pause flag if any
714714
resume(MinerPauseEnum::PauseDueToInsufficientMemory);
@@ -859,10 +859,6 @@ bool CLMiner::initEpoch_internal()
859859
// create buffer for dag
860860
try
861861
{
862-
cllog << "Creating light cache buffer, size: "
863-
<< dev::getFormattedMemory((double)m_epochContext.lightSize);
864-
m_light.clear();
865-
m_light.push_back(cl::Buffer(m_context[0], CL_MEM_READ_ONLY, m_epochContext.lightSize));
866862
cllog << "Creating DAG buffer, size: "
867863
<< dev::getFormattedMemory((double)m_epochContext.dagSize)
868864
<< ", free: "
@@ -883,6 +879,32 @@ bool CLMiner::initEpoch_internal()
883879
m_dag.push_back(
884880
cl::Buffer(m_context[0], CL_MEM_READ_ONLY, (m_epochContext.dagSize) / 2));
885881
}
882+
cllog << "Creating light cache buffer, size: "
883+
<< dev::getFormattedMemory((double)m_epochContext.lightSize);
884+
m_light.clear();
885+
bool light_on_host = false;
886+
try
887+
{
888+
m_light.emplace_back(m_context[0], CL_MEM_READ_ONLY, m_epochContext.lightSize);
889+
}
890+
catch (cl::Error const& err)
891+
{
892+
if ((err.err() == CL_OUT_OF_RESOURCES) || (err.err() == CL_OUT_OF_HOST_MEMORY))
893+
{
894+
// Ok, no room for light cache on GPU. Try allocating on host
895+
clog(WarnChannel) << "No room on GPU, allocating light cache on host";
896+
clog(WarnChannel) << "Generating DAG will take minutes instead of seconds";
897+
light_on_host = true;
898+
}
899+
else
900+
throw;
901+
}
902+
if (light_on_host)
903+
{
904+
m_light.emplace_back(m_context[0], CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR,
905+
m_epochContext.lightSize);
906+
cllog << "WARNING: Generating DAG will take minutes, not seconds";
907+
}
886908
cllog << "Loading kernels";
887909

888910
// If we have a binary kernel to use, let's try it

‎libethash-cuda/CUDAMiner.cpp

+33-14
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ bool CUDAMiner::initEpoch_internal()
8181
bool retVar = false;
8282
m_current_target = 0;
8383
auto startInit = std::chrono::steady_clock::now();
84-
size_t RequiredMemory = (m_epochContext.dagSize + m_epochContext.lightSize);
84+
size_t RequiredTotalMemory = (m_epochContext.dagSize + m_epochContext.lightSize);
85+
size_t RequiredDagMemory = m_epochContext.dagSize;
8586

8687
// Release the pause flag if any
8788
resume(MinerPauseEnum::PauseDueToInsufficientMemory);
8889
resume(MinerPauseEnum::PauseDueToInitEpochError);
8990

91+
bool lightOnHost = false;
9092
try
9193
{
9294
hash128_t* dag;
@@ -104,21 +106,34 @@ bool CUDAMiner::initEpoch_internal()
104106
CUDA_SAFE_CALL(cudaDeviceSetCacheConfig(cudaFuncCachePreferL1));
105107

106108
// Check whether the current device has sufficient memory every time we recreate the dag
107-
if (m_deviceDescriptor.totalMemory < RequiredMemory)
109+
if (m_deviceDescriptor.totalMemory < RequiredTotalMemory)
108110
{
109-
cudalog << "Epoch " << m_epochContext.epochNumber << " requires "
110-
<< dev::getFormattedMemory((double)RequiredMemory) << " memory.";
111-
cudalog << "This device hasn't available. Mining suspended ...";
112-
pause(MinerPauseEnum::PauseDueToInsufficientMemory);
113-
return true; // This will prevent to exit the thread and
114-
// Eventually resume mining when changing coin or epoch (NiceHash)
111+
if (m_deviceDescriptor.totalMemory < RequiredDagMemory)
112+
{
113+
cudalog << "Epoch " << m_epochContext.epochNumber << " requires "
114+
<< dev::getFormattedMemory((double)RequiredDagMemory) << " memory.";
115+
cudalog << "This device hasn't enough memory available. Mining suspended ...";
116+
pause(MinerPauseEnum::PauseDueToInsufficientMemory);
117+
return true; // This will prevent to exit the thread and
118+
// Eventually resume mining when changing coin or epoch (NiceHash)
119+
}
120+
else
121+
lightOnHost = true;
115122
}
116123

117-
cudalog << "Generating DAG + Light : "
118-
<< dev::getFormattedMemory((double)RequiredMemory);
124+
cudalog << "Generating DAG + Light(on " << (lightOnHost ? "host" : "GPU")
125+
<< ") : " << dev::getFormattedMemory((double)RequiredTotalMemory);
119126

120127
// create buffer for cache
121-
CUDA_SAFE_CALL(cudaMalloc(reinterpret_cast<void**>(&light), m_epochContext.lightSize));
128+
if (lightOnHost)
129+
{
130+
CUDA_SAFE_CALL(cudaHostAlloc(reinterpret_cast<void**>(&light),
131+
m_epochContext.lightSize, cudaHostAllocDefault));
132+
cudalog << "WARNING: Generating DAG will take minutes, not seconds";
133+
}
134+
else
135+
CUDA_SAFE_CALL(
136+
cudaMalloc(reinterpret_cast<void**>(&light), m_epochContext.lightSize));
122137
m_allocated_memory_light_cache = m_epochContext.lightSize;
123138
CUDA_SAFE_CALL(cudaMalloc(reinterpret_cast<void**>(&dag), m_epochContext.dagSize));
124139
m_allocated_memory_dag = m_epochContext.dagSize;
@@ -133,7 +148,7 @@ bool CUDAMiner::initEpoch_internal()
133148
else
134149
{
135150
cudalog << "Generating DAG + Light (reusing buffers): "
136-
<< dev::getFormattedMemory((double)RequiredMemory);
151+
<< dev::getFormattedMemory((double)RequiredTotalMemory);
137152
get_constants(&dag, NULL, &light, NULL);
138153
}
139154

@@ -151,7 +166,9 @@ bool CUDAMiner::initEpoch_internal()
151166
std::chrono::steady_clock::now() - startInit)
152167
.count()
153168
<< " ms. "
154-
<< dev::getFormattedMemory((double)(m_deviceDescriptor.totalMemory - RequiredMemory))
169+
<< dev::getFormattedMemory(
170+
lightOnHost ? (double)(m_deviceDescriptor.totalMemory - RequiredDagMemory) :
171+
(double)(m_deviceDescriptor.totalMemory - RequiredTotalMemory))
155172
<< " left.";
156173

157174
retVar = true;
@@ -271,7 +288,9 @@ void CUDAMiner::enumDevices(std::map<string, DeviceDescriptor>& _DevicesCollecti
271288

272289
try
273290
{
291+
size_t freeMem, totalMem;
274292
CUDA_SAFE_CALL(cudaGetDeviceProperties(&props, i));
293+
CUDA_SAFE_CALL(cudaMemGetInfo(&freeMem, &totalMem));
275294
s << setw(2) << setfill('0') << hex << props.pciBusID << ":" << setw(2)
276295
<< props.pciDeviceID << ".0";
277296
uniqueId = s.str();
@@ -288,7 +307,7 @@ void CUDAMiner::enumDevices(std::map<string, DeviceDescriptor>& _DevicesCollecti
288307
deviceDescriptor.cuDeviceIndex = i;
289308
deviceDescriptor.cuDeviceOrdinal = i;
290309
deviceDescriptor.cuName = string(props.name);
291-
deviceDescriptor.totalMemory = props.totalGlobalMem;
310+
deviceDescriptor.totalMemory = freeMem;
292311
deviceDescriptor.cuCompute =
293312
(to_string(props.major) + "." + to_string(props.minor));
294313
deviceDescriptor.cuComputeMajor = props.major;

0 commit comments

Comments
 (0)
This repository has been archived.