Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HELP] "Out of Memory" error after distributing tasks (CUDA memory cleanup) #435

Open
joaoescribano opened this issue Jan 2, 2025 · 1 comment

Comments

@joaoescribano
Copy link

Hello,
First of all, thank you for all the hard work. I'm not a C++ dev by trade, but I've been experimenting with BitCrack to create a pool-like setup for distributing work. Here's what I'm trying to achieve:

  1. Objective

    • Modify BitCrack to connect to my custom socket server (like a pool).
    • Distribute tasks such as Puzzle 67 or random wallet searches.
    • Upon completion of a task, the worker requests a new one without restarting BitCrack.
  2. What I’ve done so far

    • Edited KeyFinder.cpp to connect to my socket server using flags like:
      --pool 127.0.0.1 --user admin --pass 123 --worker bob --puzzle 67
      
    • Once connected, the server distributes the required parameters (keyspace, target, compression, etc.).
    • After finishing a task, BitCrack sends a new “job request” to the server.
  3. The issue

    • After successfully completing the first task, BitCrack attempts to request a second job.
    • Suddenly, I get this error message:
      terminate called after throwing an instance of 'KeySearchException'
      
    • Digging deeper, I found the CUDA error message:
      cudaErrorMemoryAllocation: Out of memory
      
  4. Hypothesis

    • It seems the CUDA memory isn't being cleaned up properly after the first task completes.
    • On the second task request, the GPU memory still allocated and not properly freed (almost 40% still in use), leading to an out-of-memory error.
  5. Request for Help

    • Could someone point me to where in the BitCrack codebase I could implement a proper CUDA memory cleanup routine after each cycle?
    • Is there a recommended pattern or function call I should be using in C++/CUDA to ensure the device memory is freed before requesting a new task?
  6. Additional Info

    • Environment:
      • OS: Ubuntu 24.04
      • Compiler: g++ (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
      • CUDA Version: 12
      • GPU Model: RTX 3080 TI
    • I’m open to any best practices, suggestions, or code snippets that might help handle the memory cleanup gracefully.

Thank you in advance for any help you can provide. Please let me know if there's any additional information I can provide.

@joaoescribano
Copy link
Author

joaoescribano commented Jan 2, 2025

Also, the changes i've made basicly if i receive the new arguments, i call my own method:

int runPoolMode(const std::string &host,
                unsigned short port,
                const std::string &username,
                const std::string &password,
                const std::string &workerName,
                const std::string &mode,
                const int &puzzleId)
{
    Logger::log(LogLevel::Info, "[PoolMode] Connecting to server " 
        + host + ":" + std::to_string(port));

    PoolClient client(host, port);

    try {
        client.connect();
    } 
    catch(const std::exception &e) {
        Logger::log(LogLevel::Error, 
            "[PoolMode] Connection error: " + std::string(e.what()));
        return 1;
    }

    // Efetua login
    nlohmann::json loginReq = {
        {"command",  "login"},
        {"username", username},
        {"password", password},
        {"worker",   workerName}
    };
    nlohmann::json loginResp;
    try {
        loginResp = client.sendRequest(loginReq);
    } 
    catch(const std::exception &e) {
        Logger::log(LogLevel::Error, 
            "[PoolMode] Login request error: " + std::string(e.what()));
        return 1;
    }

    if(!loginResp["status"].get<bool>()) {
        Logger::log(LogLevel::Error, 
            "[PoolMode] Login error: " + loginResp["message"].get<std::string>());
        return 1;
    }
    Logger::log(LogLevel::Info, "[PoolMode] Login successfully!");

    if (mode == "wallet") {
        Logger::log(LogLevel::Info, "[PoolMode] Wallet searh mode");
    } else {
        Logger::log(LogLevel::Info, "[PoolMode] Puzzle search mode");
    }

    // Loop para pegar tarefas
    while(true)
    {
        if (mode == "wallet") {
            // TO BE IMPLEMENTED
        } else {
            nlohmann::json getTaskReq = {
                {"command", "get_task"},
                {"type",    "puzzle"},
                {"puzzle",  puzzleId} 
            };

            nlohmann::json taskResp;
            try {
                taskResp = client.sendRequest(getTaskReq);
            }
            catch(const std::exception &e) {
                Logger::log(LogLevel::Error, 
                    "[PoolMode] Error requesting task: " + std::string(e.what()));
                return 1;
            }

            if(!taskResp["status"].get<bool>()) {
                std::string msg = taskResp.value("message", "");
                Logger::log(LogLevel::Info, 
                    "[PoolMode] Error getting task. Msg: " + msg);
                break;
            }

            // Extrair ranges do JSON
            std::string startHex = taskResp["task_start"].get<std::string>();
            std::string endHex   = taskResp["task_end"].get<std::string>();

            secp256k1::uint256 startKey(startHex);
            secp256k1::uint256 endKey(endHex);

            // Ajustar _config
            _config.startKey = startKey;
            _config.nextKey  = startKey;
            _config.endKey   = endKey;
            _config.stride   = 1;

            // Se houver "target_wallet", setar em _config.targets
            if(taskResp.contains("target_wallet")) {
                std::string targetWallet = taskResp["target_wallet"];
                _config.targets.clear();
                _config.targets.push_back(targetWallet);
            }

            // Executa a busca
            int ret = run();
            if(ret != 0) {
                Logger::log(LogLevel::Error, "[PoolMode] ended with error.");

                nlohmann::json updateReq = {
                    {"command",    "update_task"},
                    {"puzzle_id",  puzzleId},
                    {"task_block", taskResp["task_block"]},
                    {"status",     "error"}
                };

                try {
                    nlohmann::json updateResp = client.sendRequest(updateReq);
                    Logger::log(LogLevel::Info, "[PoolMode] Task updated.");
                } 
                catch(const std::exception &e) {
                    Logger::log(LogLevel::Error, 
                        "[PoolMode] Update task error: " + std::string(e.what()));
                }

                return ret;
            }

            nlohmann::json updateReq = {
                {"command",    "update_task"},
                {"puzzle_id",  puzzleId},
                {"task_block", taskResp["task_block"]},
                {"status",     "completed"}
            };

            try {
                nlohmann::json updateResp = client.sendRequest(updateReq);
                Logger::log(LogLevel::Info, "[PoolMode] Task updated successfully.");
            } 
            catch(const std::exception &e) {
                Logger::log(LogLevel::Error, 
                    "[PoolMode] Error sending update task request: " + std::string(e.what()));
            }
        }
    }
    Logger::log(LogLevel::Info, "[PoolMode] End of tasks, shutting down.");
    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant