2012-01-16 4 views
3

내 문제는 memory databaseQSql을 사용하는 것입니다. 이 공통 데이터베이스의 다른 테이블을 처리하는 여러 스레드가 있습니다. 그리고 나는이 스레드가 다음과 같이 서로 다른 프로세서 작업을 확인하기 위해 Win API를 사용멀티 프로세서 스레드에서 메모리 데이터베이스의 QSql 최적화

SetThreadAffinityMask (hThread, processorMask); 

하나 개의 테이블이 처리 스레드의, 그것은 10 초 소요, 총 CPU의 25 %를 사용합니다. 그러나 4 개의 다른 테이블을 처리하는 4 개의 스레드가있을 경우에는 거의 40 초가 걸리고 전체 CPU의 35 % 만 사용합니다. 그 이유는 어떤 종류의 thread-safe 동기화가 하나의 데이터베이스에 있다고 생각합니다. 그러나 다른 스레드 읽기 또는 다른 테이블 작성으로 인해 스레드 안전은 프로그램 속도를 저하시킵니다. 어떻게 최적화 할 수 있습니까?

업데이트 : 가장 가능한 이유는 그래서 종료 할 수 있습니다 또는 사전 설정하여 이러한 잠금을 우회, 내 프로그램을 느리게 Qt 및/또는 Sqlite 3의 내부 잠금 장치의 일부 종류입니다.

업데이트 2 : 다음은 예입니다. (어쩌면 조금 긴, 죄송합니다)

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(); 
} 
+0

이것은 실제로 sqlite3을 사용하는 방법에 따라 다릅니다. 데이터베이스로 수행중인 작업의 일부 예제를 붙여 넣으십시오. – synthesizerpatel

+0

최적화를 진행하기 전에이 질문을 살펴보십시오. http://stackoverflow.com/questions/1680249/how-to-use-sqlite-in-a-multi-threaded-application – Neox

+0

@Nox 그것은 도움이되지만 내 상황에는 약간의 차이가 있습니다. 첫째, 제 프로그램에서 직접'sqlite'가 아닌'QSql'을 사용합니다. 그래서 sqlite3 라이브러리를 컴파일하는 방법을 선택할 수 없습니다.둘째, 서로 다른 테이블에서 실행되기 때문에 스레드간에 동기화 할 필요가 없습니다. 세 번째는 메모리 데이터베이스를 사용하므로 동일한 연결을 공유해야합니다. – xucheng

답변

1

먼저 선호도 마스크를 명시 적으로 설정하지 않으면 Windows는 가장 유휴 코어에 스레드를 자동으로 할당합니다. 이 경우 OS보다 코드 배포보다 스레드 배포를 사용하는 것이 좋습니다.

필자가 아는 한, sqlite는 쓰는 동안 전체 데이터베이스를 잠급니다. 따라서 성능이 향상되지 않습니다. sqlite 잠금 설명서를 살펴보십시오. http://www.sqlite.org/lockingv3.html

0

는 비교 스레드가 디스크 I/O 처리량, 말,로 CPU에 지출 얼마나 많은 시간 측정이 있나요?

이것은 스레딩 및 잠금과 아무 관련이 없습니다. Amdahl's law과 관련이 있습니다.

+0

디스크 I/O가 전혀 없다. 메모리 데이터베이스에서 순수한 계산이다. – xucheng

+0

좋아, 그래서 디스크가 아니야.하지만 그게 중요한 게 아니야. Amdahl 효과로 인도하는 * 차단 자원 일 수 있습니다. – spraff

0

Qt 문서는 이에 대해 모호하지 않습니다. http://doc.qt.nokia.com/4.7/threads-modules.html#threads-and-the-sql-module에서 :

스레드와 SQL 모듈

연결은 그것을 만든 스레드 내에서 사용할 수 있습니다. 스레드 간 연결 이동 또는 다른 스레드에서 쿼리 작성은 지원되지 않습니다.

또한 QSqlDrivers에서 사용하는 타사 라이브러리 은 다중 스레드 프로그램에서 SQL 모듈 사용에 대한 추가 제한을 설정할 수 있습니다. 당신은 Qt는 API를 통해 원하는 것을 할 수있는 방법은 없습니다 더 정보

에 대한 데이터베이스 클라이언트의 설명서를 참조하십시오.

+0

그러나 내 코드가 실행 가능하므로 QSql btwn 스레드를 사용할 수 있습니다. 나는 그것을 최적화하는 방법을 모른다. – xucheng

+0

요점은 이것이 지원되지 않는다는 것입니다. 프로그램이 다운되거나 데이터가 손상되거나 다른 일이 발생할 수 있습니다. 개념적으로 말하자면, 잠금없이 동일한 데이터베이스의 다른 테이블에 동시에 쓰기를 시도하는 것은 의미가 없습니다. 테이블이 관련되어있어 잠금이 필요하거나 그렇지 않아서 동일한 데이터베이스에있을 필요가 없습니다. 무엇 이니? –

관련 문제