Pregunta

Aquí está mi problema, tengo uno sqlite memory database mediante el uso QSql. Tengo varios hilos que manejan una tabla diferente de esta base de datos común. Y yo uso Win API Para asegurarse de que estos hilos funcionen en diferentes procesadores, como este:

SetThreadAffinityMask (hThread, processorMask);

Cuando solo hay un hilo que maneja una mesa, toma 10 segundos y usa el 25% de la CPU total. Pero cuando hay 4 hilos que manejan 4 tablas diferentes, toma casi 40 segundos y usa solo el 35% de la CPU total. Creo que la razón es que hay algún tipo de thread-safe sincronización en una base de datos. Pero debido a la lectura de hilos diferentes o la escritura de diferentes tablas, Hort Safe ralentiza mi programa. ¿Cómo puedo optimizarlo?

Actualizar: La razón más posible es algunos tipos de bloqueo dentro de Qt o y Sqlite 3 ralentiza mi programa, por lo que es posible apagar o pasar por alto estas cerraduras mediante la presentación previa.

Actualización2: Aquí hay un ejemplo. (Tal vez un poco largo, lo siento)

class MultiProcessorThread
{
public:
    virtual void run();
    bool start()
    {
        m_hThread = CreateThread (NULL, 0, MultiProcessorThread::ThreadFunc, this, CREATE_SUSPENDED, NULL);

        if (m_hThread != INVALID_HANDLE_VALUE)
        {
            RunningThreadCount++;
            m_ProcessorMask = 1 << ( (RunningThreadCount - 1) % ProcessorCount);
            SetThreadAffinityMask (m_hThread, m_ProcessorMask); // Make thread working on different processor
            ResumeThread (m_hThread);
            return true;
        }
        else
            return false;
    }
protected:
    static DWORD WINAPI ThreadFunc (LPVOID in);
    HANDLE m_hThread;
    DWORD_PTR m_ProcessorMask;
    static DWORD_PTR ProcessorCount;
    static DWORD_PTR RunningThreadCount;
    static DWORD_PTR GetNumCPUs();
};

DWORD_PTR MultiProcessorThread::ProcessorCount = GetNumCPUs();
DWORD_PTR MultiProcessorThread::RunningThreadCount = 0;
DWORD_PTR MultiProcessorThread::GetNumCPUs() // Get how many processors on this PC
{
    SYSTEM_INFO m_si = {0};
    GetSystemInfo (&m_si);
    return (DWORD_PTR) m_si.dwNumberOfProcessors;
}
DWORD WINAPI MultiProcessorThread::ThreadFunc (LPVOID in)
{
    static_cast<MultiProcessorThread*> (in)->run();
    return 0;
}

class Run : public MultiProcessorThread
{
public:
    void run()
    {
        int i = 0;
        QString add = "insert into %1 values(1)";
        add = add.arg (table);
        QString sel = "select a from %1 ";
        sel = sel.arg (table);
        QString del = "delete from %1 where a=1";
        del = del.arg (table);

        while (++i) // read and write database
        {
            query.exec (add);
            query.exec (sel);
            query.exec (del);
        }
    }
    QSqlQuery query;
    QString table;
};  

int main (int argc, char *argv[])
{
    QCoreApplication a (argc, argv);
    QSqlDatabase db = QSqlDatabase::addDatabase ("QSQLITE", "test"); 
    db.setDatabaseName (":memory:"); // All threads working on the same memory database.
    db.open();
    QSqlQuery q (db), q1 (db), q2 (db);
    q.exec ("create table A (a)");
    q1.exec ("create table B (a)");
    q2.exec ("create table C (a)"); // All threads working on different table.
    Run b[3];
    b[0].query = QSqlQuery (q);
    b[0].table = "A";
    b[1].query = QSqlQuery (q1);
    b[1].table = "B";
    b[2].query = QSqlQuery (q2);
    b[2].table = "C";
    b[0].start();
    b[1].start();
    b[2].start();
    return a.exec();
}
¿Fue útil?

Solución

En primer lugar, no configure la máscara de afinidad explícitamente, Windows asignará automáticamente hilos en los núcleos más inactivos. Es mejor confiar en el sistema operativo para hacer una distribución de hilos que su código en este caso.

Hasta donde yo sé, SQLite bloquea la base de datos completa mientras escribe, por eso no obtienes un aumento de rendimiento que esperabas. Eche un vistazo a la documentación de bloqueo de SQLite http://www.sqlite.org/lockingv3.html

Otros consejos

¿Ha medido cuánto tiempo pasan los hilos en la CPU en comparación con, por ejemplo, el rendimiento de E/S de disco?

Esto no podría tener nada que ver con el enhebrado y las cerraduras. Podría tener todo que ver con Ley de Amdahl.

Los documentos QT son inequívocos sobre esto. De http://doc.qt.nokia.com/4.7/threads-modules.html#threads-and-the-sql-module:

Hilos y el módulo SQL

Una conexión solo se puede usar desde el hilo que la creó. No es compatible con las conexiones de mover entre hilos o crear consultas desde un hilo diferente.

Además, las bibliotecas de terceros utilizadas por los QSQLDRivers pueden imponer restricciones adicionales al usar el módulo SQL en un programa multiproceso. Consulte el manual del cliente de su base de datos para obtener más información

No hay forma de hacer lo que quieres a través de la API QT.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top